How to Instrument Cloudflare Worker in 2026: 4 Proven Ways


What Does It Mean to Instrument a Cloudflare Worker?

To instrument a Cloudflare Worker is to embed code or configuration that captures telemetry data (metrics, traces, and logs) while the Worker handles requests. The goal is observability: understanding what your code does at the edge, how fast it runs, and where it fails.

This sounds straightforward if you’ve instrumented a traditional Node.js server. It isn’t. Workers execute in V8 isolates across Cloudflare’s global network, and that runtime environment breaks assumptions that most observability tools depend on. The result is that instrumenting a Cloudflare Worker requires different tools, different patterns, and a different mental model than what you’d use on a regular server.

If you’re new to the serverless computing model, the short version is: your code runs on demand, scales to zero, and the platform handles infrastructure. That convenience comes with constraints that matter a lot for observability.

Explore Distlang Metrics, an API-first metrics service built for serverless and edge runtimes like Cloudflare Workers.

Why Standard APM Tools Don’t Work in Workers

Traditional application performance monitoring relies on agents that attach to a long-running process, hook into Node.js internals, and ship data in the background. None of that works in the Workers runtime.

Here’s why:

No Node.js APIs. Workers run on V8 directly, not on Node.js. There’s no fs, no net, no http module. Standard OpenTelemetry Node.js SDKs will fail at import time because they depend on these modules.

No long-running process. APM agents assume they can attach to a process that stays alive for hours or days, buffering and flushing telemetry on a schedule. Workers isolates are stateless and short-lived. They may be reused across requests on the same edge location, but there’s no guaranteed longevity.

Clock restrictions. The Workers runtime deliberately limits timing accuracy to protect against side-channel attacks like Spectre. The clock only updates on I/O operations, which means CPU-heavy processing appears to take 0 milliseconds. This makes naive latency measurements unreliable.

No filesystem or native modules. Many APM libraries use native C++ addons or write to disk. Neither is possible in a Worker.

For a deeper walkthrough of what actually works, see our guide to instrumenting Workers with counters and histograms.

The Core Pattern: ctx.waitUntil() and Flush Semantics

Every approach to instrument a Cloudflare Worker depends on one primitive: ctx.waitUntil(). Understanding it is non-negotiable.

How waitUntil Works

ctx.waitUntil() accepts a Promise and tells the runtime to keep the isolate alive until that Promise resolves, even after the response has been sent to the client. This lets you do background work (sending logs, flushing metrics, writing to a cache) without adding latency to the response.

This is precisely what makes it the backbone of Worker instrumentation. You handle the request, send a response, then use waitUntil to ship your telemetry data.

The Flush Problem

Here’s where developers get burned. Practitioners on DEV Community report a common misconception: “I’ll just use ctx.waitUntil() to let it finish after the response!” But as one developer discovered, waitUntil doesn’t extend the timeout. The isolate still shuts down at the same time limit. You get cleanup time, not extra time.

PostHog’s Cloudflare Workers documentation spells out the practical consequence: batched data sent asynchronously can be lost if the Worker terminates before the batch is sent. Their recommendation is to set flushAt: 1 and flushInterval: 0 to send data immediately rather than batching it.

The Langfuse team echoes this pattern. The root cause, they explain, is that serverless functions are short-lived and terminate after execution. Background agents may not have enough time to complete their work. The fix is always the same: manually flush before the function exits.

Best Practices for Reliable Telemetry

  1. Flush per request. Don’t rely on batch intervals. Call flush() explicitly inside ctx.waitUntil().
  2. Keep payloads small. You have a 30-second window after the response, but less is better.
  3. Don’t destructure ctx. Pulling waitUntil off the context object loses the this binding and throws “Illegal invocation.” Pass ctx as a whole object.

For detailed configuration options, read about buffering and flush behavior in JavaScript metrics clients.

Four Ways to Instrument a Cloudflare Worker

There’s no single right answer. The best approach depends on what you need to observe, what tools your team already uses, and how much setup you’re willing to tolerate.

1. API-First Metrics Services

Sometimes you don’t need distributed tracing. You need to count things, measure latency distributions, and see a dashboard. For this use case, API-first metrics services send data points via HTTP directly from Worker code.

This approach is serverless-native by design. There are no agents to install, no sidecars, no time-series databases to manage. You define your metrics in code, record values during request handling, and flush via ctx.waitUntil().

Distlang Metrics provides a Cloudflare Workers quickstart for exactly this pattern, with a lightweight JavaScript client and a hosted dashboard that auto-generates from your metric definitions.

2. Cloudflare’s Built-In Observability

Cloudflare has invested heavily in first-party observability. If you want to instrument a Cloudflare Worker with zero external dependencies, this is where to start.

Automatic Tracing (Open Beta). Cloudflare’s Workers Tracing automatically instruments every I/O operation through a deep integration in workerd, their runtime. No code changes required. You enable it by setting observability.traces.enabled = true in your Wrangler configuration. KV reads, R2 operations, Durable Object invocations, and other binding calls are automatically traced. The traces follow OpenTelemetry standards, making them compatible with Honeycomb, Grafana Cloud, and Axiom.

Built-In Metrics Dashboard. Cloudflare provides request counts, error rates, CPU time, wall time, and execution duration out of the box. You can inspect these metrics for up to three months in maximum increments of one week.

Workers Analytics Engine. For custom data points (signups per route, feature flag evaluations, anything application-specific), the Analytics Engine provides unlimited-cardinality analytics via a write API and a SQL query API. Writes are non-blocking and add no latency. The limit is 250 data points per invocation with three-month retention.

Workers Observability Dashboard. Launched in late 2025, this new dashboard section lets you query detailed log events across all Workers in your account with a built-in query builder.

Cost note: Starting March 1, 2026, tracing is billed as part of Workers usage. Sampling (tracing a percentage of requests) becomes a cost lever. Configure it to balance insight against volume.

3. OpenTelemetry Libraries

For teams that want distributed tracing across multiple services (not just Workers), the community library @microlabs/otel-cf-workers is the standard choice. It wraps your Worker’s fetch handler with an instrumentation layer, creating a root span for every incoming request and providing context for child spans.

The setup involves installing the library, wrapping your handler with instrument(), and configuring an OTLP HTTP endpoint. You add custom spans for KV lookups, Durable Object calls, and external API requests, then use ctx.waitUntil() to flush traces.

One important limitation: metrics export via OpenTelemetry from Workers is not yet supported. Only traces and logs can be exported today. If you need custom application metrics (counters, histograms), you’ll need to pair OTel tracing with another approach for metrics.

4. Vendor-Specific SDKs

If your team already uses Sentry, PostHog, New Relic, or a similar platform, each offers Workers-compatible patterns. New Relic, for example, combines its HTTPS log endpoint with event.waitUntil() for non-blocking instrumentation. Sentry has a Workers-specific SDK.

The common thread across all vendors is the same flush concern. PostHog explicitly recommends setting flushAt: 1 and flushInterval: 0 for Workers. Any vendor SDK that batches asynchronously will lose data in short-lived handlers unless you override the defaults.

Key Metrics to Track

Infrastructure Metrics

Cloudflare provides these automatically:

CPU time. The CPU time per execution chart shows historical data broken down by quantiles. Higher quantiles may appear to exceed CPU limits without generating errors, because the Workers runtime allows rollover CPU time for requests below the limit.

Wall time. This measures elapsed milliseconds from invocation start until no more JavaScript needs to run, including time spent waiting on I/O and time inside waitUntil() handlers.

Invocation status. These indicate whether a Worker executed successfully or failed to generate a response. They’re different from HTTP status codes and are worth monitoring separately.

Subrequests. Broken down by cached vs. uncached, these tell you how your Worker interacts with upstream services and Cloudflare’s cache.

Application Metrics

Infrastructure metrics tell you if your Worker is healthy. Application metrics tell you if your product is working. These include:

  • Counters: signups, purchases, API calls by endpoint, feature usage
  • Histograms: response latency distributions, payload sizes, queue depths
  • Gauges: active sessions, items in a processing queue

Cloudflare’s built-in metrics cover the infrastructure side. For application-level counters and histograms, you need Analytics Engine, an OTel setup, or an API-first metrics service. To see what the full flow looks like, our end-to-end example walks through going from code to a live dashboard.

Common Pitfalls When You Instrument a Cloudflare Worker

Forgetting to flush. The most common mistake. If you record metrics or traces but don’t explicitly flush inside waitUntil(), data will be lost when the isolate shuts down. The Inngest blog notes that waitUntil does not ensure success: if the promise fails, the Worker still returns a response, but your telemetry is gone.

Destructuring ctx. Writing const { waitUntil } = ctx and then calling waitUntil(promise) throws “Illegal invocation” because the method loses its this binding. Always call ctx.waitUntil() directly.

Treating waitUntil as infinite. The isolate has a 30-second limit after the response is sent. Long-running background work will be killed.

Installing Node.js OTel packages. Packages like @opentelemetry/sdk-trace-node depend on Node.js internals. They won’t work. Use @microlabs/otel-cf-workers or Cloudflare’s built-in tracing instead.

Over-instrumenting. Every span, every metric write, every log line costs CPU time. Instrument what matters, not everything. If you’re hitting CPU limits, reduce the telemetry before optimizing your business logic.

For more on managing payload sizes and ingestion patterns, see our guide on batching and payload limits.

When to Use What: Comparing Approaches

Criteria API-First Metrics Built-In Tracing OpenTelemetry Vendor SDK
Setup effort Low (client + API key) Minimal (config flag) Moderate (library + config) Moderate (SDK + config)
Custom app metrics Yes (counters, histograms) Via Analytics Engine Not yet supported Varies by vendor
Distributed tracing No Yes Yes Varies
External tool required Yes (metrics service) Optional (can export) Yes (OTLP endpoint) Yes (vendor platform)
Cost control Per-row pricing Sampling config Sampling + endpoint costs Vendor pricing
Best for App-level counters/histograms Teams starting fresh Multi-service architectures Teams already on a platform

If you need custom business metrics without the overhead of a full observability stack, an API-first approach fits. If you’re already on Cloudflare and just need visibility, start with built-in tracing. If you’re running a distributed architecture across multiple providers, OTel gives you cross-service correlation.

For a step-by-step walkthrough of the metrics quickstart guide, from writing your first counter to seeing it on a dashboard, that guide covers the full path.

Getting Started

The fastest way to instrument a Cloudflare Worker depends on what you need:

  • For application metrics: Pick an API-first service like Distlang Metrics or use Analytics Engine, define your metrics in code, flush inside ctx.waitUntil().
  • For infrastructure visibility: Enable observability.traces.enabled = true in wrangler.toml. Done.
  • For distributed tracing: Install @microlabs/otel-cf-workers, wrap your handler, point to your OTLP endpoint.

Whichever path you choose, the pattern is the same: capture data during the request, flush it after the response, and make sure the flush completes before the isolate shuts down.

Get started with Distlang Metrics on Cloudflare Workers in minutes, with a free tier that includes 500k rows per month.

FAQ

What does it mean to instrument a Cloudflare Worker?

It means adding telemetry collection (metrics, traces, logs) to your Worker so you can monitor its behavior, performance, and errors. Because Workers run in V8 isolates rather than Node.js, this requires specialized tools and patterns.

Why can’t I use standard Node.js APM agents in Workers?

Workers run on V8 directly without Node.js APIs. There’s no filesystem, no native modules, and no long-running process for an agent to attach to. Libraries that depend on fs, net, or http will fail at import time.

What is ctx.waitUntil() and why does it matter for instrumentation?

ctx.waitUntil() keeps the Worker isolate alive after the response is sent, giving you time to flush telemetry data without adding latency to the user’s response. It’s the foundational pattern behind all Worker instrumentation approaches.

Will I lose telemetry data if I batch it in a Worker?

Yes, this is a real risk. If the Worker terminates before a batched send completes, that data is lost. The recommended practice is to flush per request (set flushAt: 1 and flushInterval: 0) or call flush() explicitly inside ctx.waitUntil().

Does Cloudflare’s automatic tracing cost money?

Starting March 1, 2026, tracing is billed as part of Workers usage on Free, Paid, and Enterprise plans. You can configure sampling to trace only a percentage of requests, which helps manage costs.

Can I export OpenTelemetry metrics from Workers?

Not yet. As of now, only traces and logs can be exported via OpenTelemetry from Workers. Metrics export is on Cloudflare’s roadmap. For custom application metrics, use Workers Analytics Engine or an external metrics service.

What’s the difference between infrastructure metrics and application metrics?

Infrastructure metrics (CPU time, wall time, error rate) come from Cloudflare’s built-in dashboard and tell you about Worker health. Application metrics (signups, feature usage, latency by endpoint) require custom instrumentation and tell you about product behavior.

How do I avoid the “Illegal invocation” error with waitUntil?

Don’t destructure ctx. Instead of writing const { waitUntil } = ctx, always call ctx.waitUntil(promise) directly. Destructuring breaks the this binding that the method depends on.