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
Yourwrangler.jsonc must include the nodejs_compat compatibility flag (required for AsyncLocalStorage and crypto):
Quick Start
Wrap your Worker handler withwithSquasher. This automatically captures unhandled errors and flushes events via ctx.waitUntil():
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:
withSquashercalls your config function withenvto get the API key and project ID- Wraps your handler in a try/catch
- On error: captures the error with full stack trace and context
- After the handler returns (or throws): flushes all buffered events via
ctx.waitUntil() - Events are sent to
ingest.squasher.aiusing the globalfetch()API
Manual Capture
Inside awithSquasher-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.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.
Breadcrumbs
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
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
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:
Cross-process traces
Injecttraceparent 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()andDate.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.