Edge Runtimes
Learn how to use VedaTrace with edge runtimes like Cloudflare Workers, Deno, and Bun.
VedaTrace automatically detects and adapts to edge runtimes. This guide covers the supported runtimes and how to configure the SDK for optimal behavior.
Supported Runtimes
VedaTrace automatically detects the following edge runtimes:
- Cloudflare Workers - Serverless workers on Cloudflare's network
- Deno - The secure JavaScript runtime
- Bun - The all-in-one JavaScript runtime
Automatic Detection
VedaTrace automatically detects which runtime your code is running on:
import { detectRuntime, isEdgeRuntime } from 'vedatrace'
const runtime = detectRuntime()
// Returns: 'node' | 'browser' | 'cloudflare' | 'deno' | 'bun' | 'edge'
const isEdge = isEdgeRuntime()
// Returns: true for cloudflare, deno, bun, edgeEnvironment Comparison
Each runtime has different constraints for background work. VedaTrace adapts to each:
| Environment | Strategy | Flush Trigger | Automatic Delivery |
|---|---|---|---|
| Node.js (backend) | Batch timer | Every 3s + beforeExit/SIGTERM/SIGINT | Yes — process stays alive |
| Browser (frontend) | Batch + lifecycle | Every 3s + pagehide/visibilitychange | Yes — browser keeps page alive |
| Bun / Deno | Batch timer (unref'd) | Every 3s | Yes — runtime stays alive |
| Cloudflare Workers | waitUntil-based flush | queueMicrotask after each log call | Requires waitUntil config or execution context |
Cloudflare Workers
Cloudflare Workers terminate execution shortly after returning a Response. Any pending asynchronous operations — including in-flight HTTP requests to send logs — are cancelled immediately.
To reliably send logs, VedaTrace needs to register the flush operation with the Workers runtime so it keeps the worker alive until the HTTP request completes.
Approach 1: waitUntil config (recommended)
Pass the waitUntil function from cloudflare:workers in your config. VedaTrace automatically calls it to extend the worker's lifetime during log flushing.
import { vedatrace } from 'vedatrace'
import { waitUntil } from 'cloudflare:workers'
const logger = vedatrace({
apiKey: env.VEDATRACE_API_KEY,
service: 'my-worker',
waitUntil, // Keeps worker alive during log delivery
})
export default {
async fetch(request) {
logger.info('Request received', { url: request.url })
return new Response('Hello')
}
}Logs flush automatically — no need to manually call logger.flush().
Approach 2: Execution context with .withContext(ctx)
If you have access to the ctx parameter from fetch(request, env, ctx) or export default { fetch(request, env, ctx) }:
import { vedatrace } from 'vedatrace'
const logger = vedatrace({
apiKey: env.VEDATRACE_API_KEY,
service: 'my-worker',
})
export default {
async fetch(request, env, ctx) {
// Attach the Cloudflare execution context
logger.withContext(ctx)
logger.info('Request received', { url: request.url })
return new Response('Hello')
}
}.withContext(ctx) stores the ctx object, and VedaTrace uses ctx.waitUntil() to keep the worker alive during log flushing.
Approach 3: Manual ctx.waitUntil (legacy)
If you prefer to control flushing explicitly:
import { vedatrace } from 'vedatrace'
const logger = vedatrace({
apiKey: env.VEDATRACE_API_KEY,
service: 'my-worker',
})
export default {
async fetch(request, env, ctx) {
logger.info('Request received', { url: request.url })
// Ensure logs are sent before response
ctx.waitUntil(logger.flush())
return new Response('Hello')
}
}Passing waitUntil in TanStack Start
TanStack Start on Cloudflare Workers uses route handlers that receive a generic context object — not the Cloudflare ExecutionContext. Import waitUntil from cloudflare:workers directly:
import { createAPIFileRoute } from '@tanstack/react-start/api'
import { vedatrace } from 'vedatrace'
import { waitUntil } from 'cloudflare:workers'
const logger = vedatrace({
apiKey: import.meta.env.VITE_VEDATRACE_API_KEY,
service: 'pos-plus-backend',
waitUntil,
})
export const APIRoute = createAPIFileRoute('/api/test')({
GET: async ({ request, context }) => {
logger.info('Test endpoint hit')
return Response.json({ ok: true })
}
})No manual .flush() needed — VedaTrace handles it automatically.
Deno
VedaTrace works with Deno with automatic edge runtime detection:
import { vedatrace } from 'vedatrace'
const logger = vedatrace({
apiKey: Deno.env.get('VEDATRACE_API_KEY') ?? '',
service: 'my-deno-app'
})
logger.info('Deno app started')Deno keeps the process alive for pending async operations, so the standard batch timer works reliably.
Bun
VedaTrace works with Bun with automatic edge runtime detection:
import { vedatrace } from 'vedatrace'
const logger = vedatrace({
apiKey: process.env.VEDATRACE_API_KEY ?? '',
service: 'my-bun-app'
})
logger.info('Bun app started')Accessing Runtime Information
You can access the detected runtime from the logger instance:
const logger = vedatrace({ apiKey: 'xxx' })
console.log(logger.runtime)
// 'node' | 'browser' | 'cloudflare' | 'deno' | 'bun' | 'edge'Forcing a Runtime
For testing or specific scenarios, you can force a specific runtime:
const logger = vedatrace({
apiKey: 'xxx',
runtime: 'node' // Force Node.js behavior
})Manual Timer Control
For edge runtimes, you can manually control the flush timer:
const logger = vedatrace({
apiKey: 'xxx',
autoStart: false
})
// Start the timer when appropriate
logger.start()
// Do some work
logger.info('Task 1')
// Stop the timer when done
logger.stop()Flush Interval for Edge
The default flush interval is adjusted for edge runtimes:
- Edge runtimes: 1000ms
- Node.js/Browser: 5000ms
You can override this in configuration:
const logger = vedatrace({
apiKey: 'xxx',
flushInterval: 2000 // Custom interval
})