DEV Community

Cover image for Name Cloudflare Cron Triggers in Sentry
Dave Kurian
Dave Kurian

Posted on Originally published at otf-kit.dev

Name Cloudflare Cron Triggers in Sentry

A scheduled Worker can run on time and still leave monitoring hard to read. When Sentry labels a check-in with a raw cron expression, the schedule is not a useful name for the job that failed.

Sentry JavaScript 11.7.0 adds opt-in monitoring for Cloudflare Cron Triggers and a callback for assigning stable monitor slugs. Map each configured expression to a name your team recognizes, then use that same mapping in monitoring and job dispatch. The release says the monitor is created on its first run, and the integration is opt-in because monitors are billed.

Dex and Nova align a schedule token with the same task marker on a dispatcher and monitor.

Conceptual illustration of a schedule-to-monitor mapping; not a Sentry interface.

Why the expression is a poor monitor name

Cloudflare Cron Triggers do not have individual names. The scheduled handler receives the expression in controller.cron; for a Worker with triggers such as 0 9 * * MON-FRI and 0 2 * * SUN, that expression is the identifier available to the handler. A five-field schedule can look unfamiliar to a team trying to understand which business job is represented.

An expression tells you when a job runs. It does not tell the on-call engineer whether the job sends a daily report, expires sessions, or reconciles subscriptions. Sentry's default expression-derived slug can be valid and still be operationally opaque. If you run multiple schedules, map each expression to a stable, descriptive slug.

The underlying problem is the same one that makes background jobs easy to overlook: the timer is infrastructure, while the scheduled work is a product responsibility. A good monitor name should make the responsibility visible without asking someone to decode cron syntax during an incident.

If you are new to the monitoring workflow, start with our Sentry issue triage workflow. For the scheduling side, our Cloud cron jobs guide covers job design and idempotency on a different platform; the same operational habits apply, but the Cloudflare and Vercel configuration APIs are not interchangeable.

Create an explicit expression-to-slug map

Start with the expressions in your Wrangler configuration and give every production schedule a short slug that describes its work. Keep the map in source control beside the Worker so reviewers can compare the names with the actual trigger list.

// src/monitorSlugs.ts
export const monitorSlugs: Record<string, string> = {
  "0 9 * * MON-FRI": "weekday-report",
  "0 2 * * SUN": "weekly-session-cleanup",
};
Enter fullscreen mode Exit fullscreen mode

The keys must match the cron expressions that Cloudflare sends to the scheduled handler. Copy them from the Worker configuration rather than retyping them from memory. Names such as weekday-report and weekly-session-cleanup are easier to scan than a five-field schedule, and they remain stable when the job's implementation changes.

Treat this map as part of the trigger configuration, not a second informal list. A small check in your test suite can compare the configured trigger expressions with the keys in monitorSlugs: fail if a configured expression has no slug, and fail if the map contains an expression that is no longer configured. That catches a monitoring gap in review instead of after the first missed check-in.

If you deploy separate staging and production Workers, use a deliberate naming policy for the environments. Keep the workload portion recognizable and make the environment distinction explicit when those monitors need separate ownership or alert routing. Do not assume that a slug from one environment will make the other environment obvious.

Register the Sentry integration

The 11.7.0 release adds cronTriggersIntegration for @sentry/cloudflare. With the Sentry Cloudflare Vite plugin, register it in the server instrumentation file and look up the slug by the cron expression:

import * as Sentry from "@sentry/cloudflare";
import { monitorSlugs } from "./monitorSlugs";

export default Sentry.defineCloudflareOptions((env) => ({
  dsn: env.SENTRY_DSN,
  integrations: [
    Sentry.cronTriggersIntegration({
      monitorSlug: (cron) => monitorSlugs[cron],
    }),
  ],
}));
Enter fullscreen mode Exit fullscreen mode

This callback is the important part: it turns the incoming schedule into a stable monitor identifier. Keep the integration opt-in, as Sentry does. Its release notes explicitly call out that monitors are billed, so decide which production jobs deserve this monitoring before enabling it broadly. Confirm the current billing details in your Sentry account before rollout; this guide does not assume a price or plan allowance.

When you configure the Worker directly with Wrangler rather than the Vite plugin, the release notes say to pass the same integration to Sentry.withSentry. Keep the slug mapping shared between instrumentation and the scheduled handler so monitoring and execution cannot quietly drift into separate naming systems.

Dispatch the same job from the handler

Use the same map to decide which work should run. That gives the monitoring callback and the handler one source of truth:

import { monitorSlugs } from "./monitorSlugs";

export default {
  async scheduled(controller, env, ctx) {
    switch (monitorSlugs[controller.cron]) {
      case "weekday-report":
        await sendWeekdayReport(env);
        break;

      case "weekly-session-cleanup":
        await cleanExpiredSessions(env);
        break;

      default:
        console.error("Unmapped cron expression", controller.cron);
    }
  },
};
Enter fullscreen mode Exit fullscreen mode

The Sentry release example uses this same pattern: look up controller.cron in the map, then dispatch on the descriptive slug. The default branch matters. A newly configured trigger without an implementation should be visible in logs, not silently treated as a successful job. Keep each handler idempotent where retries are possible, and make the job's success or failure observable through the normal exception and check-in path.

Byte and Nova review an opt-in monitoring switch beside a scheduler and coin tray.

Conceptual illustration of choosing billable monitoring scope; not a Sentry interface.

Sentry allows the monitorSlug callback to return undefined to send no check-ins for a trigger. That gives you a useful deliberate exclusion for schedules that do not need a Sentry monitor. It also means a typo or missing map entry can suppress the check-in, so the configuration test should catch omissions before deploy. If you intend every configured production trigger to be monitored, make the test require a slug for every production expression.

Verify the mapping before rollout

A focused rollout has four checks:

  1. Compare the config and map. Every production cron expression has exactly one intended slug, and removed triggers have no stale mapping.
  2. Exercise each handler branch. Use your Worker runtime's documented scheduled-event test path with each expression so you know the right job runs.
  3. Inspect the first check-in. The release notes say Sentry creates the monitor on the first run. Confirm the monitor uses the mapped slug and that the expected schedule is represented before relying on alerts.
  4. Check the billable scope. Monitoring is opt-in because monitors are billed. Enable only the schedules your team has chosen to monitor, and confirm your account's current pricing and allowance.

Keep the mapping stable across ordinary code changes. Renaming a job should be a deliberate monitoring change, because dashboards, alert rules, runbooks, and ownership notes may refer to the slug. If the cron expression itself changes but the job is the same, preserve the descriptive slug by updating the map key instead of renaming the monitor.

Use a dashboard starter only for the UI

If you are also building the app's admin surface, the SaaS Dashboard kit is an optional UI and app-source starting point. Its live page describes editable Vite, React, Hono, and Postgres source with dashboards, projects, teams, and data tables; the listed one-time kit price is $99. It does not include Cloudflare Cron Triggers or Sentry monitoring. You still implement the cron configuration, Sentry integration, monitor names, and operational policies in your own app.

That distinction matters: a dashboard can make job status easier for your team to inspect, but it does not create check-ins or monitor schedules by itself. Wire the real runtime events first, then decide whether your application needs a separate UI for those signals.

Sources

Top comments (0)