Skip to content

Sentry.metrics.* triggers setTimeout outside request context in Cloudflare Workers #20888

@sergical

Description

@sergical

Problem

Sentry.metrics.* (count, gauge, distribution) is exported and enabled by default in @sentry/cloudflare, but capturing a metric triggers a setTimeout(..., 5000) that fires outside the request context, causing a Cloudflare Workers runtime error.

This is particularly visible when bundling with @cloudflare/vite-plugin (which applies stricter runtime checks than older Wrangler builds).

Root Cause

The core client's setupWeightBasedFlushing (packages/core/src/client.ts:105-158) registers an afterCaptureMetric hook that schedules a 5-second setTimeout (DEFAULT_FLUSH_INTERVAL = 5000) to batch-flush the metric envelope. In Cloudflare Workers, this timer fires after the request handler returns, violating the request-scoped execution model.

// packages/core/src/client.ts:139-152
} else if (!isTimerActive) {
  isTimerActive = true;
  flushTimeout = safeUnref(
    setTimeout(() => {
      flushFn(client);
    }, DEFAULT_FLUSH_INTERVAL),
  );
}

The CloudflareClient.flush() method handles pending spans but does not address the metric flush timer created by the base client.

Current Workarounds

  1. Disable standalone metrics and use span attributes/span metrics instead:
    Sentry.init({ enableMetrics: false });
  2. Call Sentry.flush() at the end of every request — this triggers the flushMetrics hook which clears the timer, but the timer still gets created before being cancelled.

Possible Fixes

  • Make DEFAULT_FLUSH_INTERVAL configurable (e.g. metricsFlushInterval option), allowing @sentry/cloudflare to set it to 0 for synchronous flushing.
  • Have @sentry/cloudflare override the flushing strategy to flush synchronously within the request context rather than relying on background timers.
  • At minimum, document that Sentry.metrics.* is not fully supported in Workers and recommend span metrics.

Context

  • Related to [Metrics] Support cloudflare workers #11220 (closed in 2024 as "won't do" when the old metrics.increment()/metrics.set() API was replaced with span-attribute-based metrics). However, Application Metrics (Sentry.metrics.count/gauge/distribution) is a newer product that shipped after that decision, so the closure rationale no longer fully applies.
  • Span metrics migration docs

Package

@sentry/cloudflare

Metadata

Metadata

Assignees

No one assigned
    No fields configured for issues without a type.

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions