Skip to main content

Overview

@squasher/edge is Squasher’s SDK for Cloudflare Workers, Cloudflare Pages, and other edge runtimes where Node.js APIs like process are not available.
If you’re running Node.js on a traditional server or in a container (Railway, Fly, AWS Lambda), use @squasher/node instead. For Next.js specifically, use @squasher/nextjs.

Install

Prerequisites

Your wrangler.jsonc must include the nodejs_compat compatibility flag (required for AsyncLocalStorage and crypto):

Quick Start

Wrap your Worker handler with withSquasher. This automatically captures unhandled errors and flushes events via ctx.waitUntil():
That’s it. Any unhandled error thrown from your fetch, queue, or scheduled handler is automatically captured, sent to Squasher, and re-thrown.

How It Works

withSquasher() creates a fresh client for every invocation (not a long-lived singleton). This matches how Cloudflare Workers operate — each request is an independent execution context. The lifecycle for each request:
  1. withSquasher calls your config function with env to get the API key and project ID
  2. Wraps your handler in a try/catch
  3. On error: captures the error with full stack trace and context
  4. After the handler returns (or throws): flushes all buffered events via ctx.waitUntil()
  5. Events are sent to ingest.squasher.ai using the global fetch() API
If a single invocation captures multiple events, the SDK groups them into as few ingest requests as possible and automatically splits large flushes into smaller requests.

Manual Capture

Inside a withSquasher-wrapped handler, you can manually capture errors and messages:

Messages

Tags and Context

Actionable Error Attributes

Edge errors can include AI-triage-friendly attributes. These make the error useful to engineers and agents without requiring them to infer every next step from the stack trace.
Unhandled errors captured by withSquasher are marked fatal when they come from a failed invocation. The SDK also records normalized request attributes such as method, route, status, handler type, duration, and service name for fetch, queue, and scheduled handlers.

Tracing, Logs, and Metrics

@squasher/edge exposes a small OpenTelemetry-compatible API for spans, structured logs, and metrics. Same shape as standard OTel — pure OTLP wire format under the hood, so no vendor lock-in. The active span is tracked through AsyncLocalStorage, so logs and metrics emitted inside a span automatically attach to it. Nested span() calls auto-parent.

span(name, fn) — one-line spans

With kind and attributes:
If the function throws, the span is marked status: "error", the error is captured with stack, and the error is re-thrown unchanged.

startSpan(name, opts?) — manual lifecycle

Use when the start and end are not in the same scope (e.g., across an event emitter):

getActiveSpan() — read current trace context

W3C traceparent propagates the trace across process boundaries. The receiving service reconstructs the parent and continues the same trace.

log.{debug, info, warn, error}(message, attrs?)

log.error accepts an Error directly and captures the stack. Logs emitted inside a span auto-correlate via trace.id and span.id attributes.

recordMetric(name, value, opts?)

type defaults to "gauge". Metrics inside a span auto-attach the trace context.

runWithSquasher(config, fn) — Durable Object scope

withSquasher only covers your top-level handler. If you call span() / log / recordMetric from a Durable Object method (or any code path that runs outside the handler), wrap it with runWithSquasher:
Without this, calls outside the handler-scoped client are no-ops.

Cross-process traces

Inject traceparent on outbound HTTP, then on the receiving end pass parent to span():

Supported Handlers

withSquasher wraps all Cloudflare Worker handler types:

Configuration

Tracing API Reference

Environment Variables

Set your API key and project ID as Worker secrets:

Differences from @squasher/node

Known Limitations

  • Span durations show 0ms: In Cloudflare Workers, performance.now() and Date.now() only advance after I/O. CPU-bound operations show zero duration.
  • 30 events per invocation: Hard buffer cap to prevent unbounded memory usage in short-lived Workers.
  • Retry backoff is shorter: Max 3s backoff (vs 30s in Node SDK) to stay within Workers’ wall-clock limits.

Agent handoff