logo

Vedatrace

Javascript sdk

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, edge

Environment Comparison

Each runtime has different constraints for background work. VedaTrace adapts to each:

EnvironmentStrategyFlush TriggerAutomatic Delivery
Node.js (backend)Batch timerEvery 3s + beforeExit/SIGTERM/SIGINTYes — process stays alive
Browser (frontend)Batch + lifecycleEvery 3s + pagehide/visibilitychangeYes — browser keeps page alive
Bun / DenoBatch timer (unref'd)Every 3sYes — runtime stays alive
Cloudflare WorkerswaitUntil-based flushqueueMicrotask after each log callRequires 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.

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
})

On this page