Home › Cloudflare Workers Cron Triggers

Cloudflare Workers Cron Triggers

How to schedule Cloudflare Workers with cron triggers. Configure schedules in wrangler.toml, handle them in the scheduled() handler, and test locally. Covers syntax, multiple triggers and plan limits.

How Cloudflare Cron Triggers Work

Cloudflare Workers cron triggers invoke a Worker's scheduled() handler on a schedule defined in wrangler.toml. Unlike HTTP-triggered Workers, cron Workers do not receive an HTTP request - they receive a ScheduledController object with the cron expression that fired. Official reference: Cloudflare Workers Scheduled Handler docs.

  • All triggers run in UTC. No per-trigger timezone option.
  • Minimum granularity is 1 minute.
  • Cloudflare supports standard 5-field cron plus Quartz-style extensions (L, W, #).
  • Triggers are registered automatically on wrangler deploy - no separate API call needed.

wrangler.toml Configuration

Add a [triggers] section to your wrangler.toml with a crons array:

# wrangler.toml
name = "my-worker"
main = "src/index.js"
compatibility_date = "2026-01-01"

[triggers]
crons = [
  "*/5 * * * *",   # every 5 minutes
  "0 2 * * *"      # daily at 2 AM UTC
]

Or using wrangler.jsonc:

{
  "name": "my-worker",
  "main": "src/index.js",
  "compatibility_date": "2026-01-01",
  "triggers": {
    "crons": ["*/5 * * * *", "0 2 * * *"]
  }
}

The scheduled() Handler

Export a scheduled() function from your Worker to handle cron triggers:

// JavaScript
export default {
  async scheduled(controller, env, ctx) {
    console.log(`Cron trigger: ${controller.cron}`);
    ctx.waitUntil(doScheduledWork(env));
  }
};
// TypeScript
export default {
  async scheduled(
    controller: ScheduledController,
    env: Env,
    ctx: ExecutionContext
  ) {
    ctx.waitUntil(doScheduledWork(env));
  }
} satisfies ExportedHandler<Env>;

Use ctx.waitUntil() for async work

The scheduled() handler has a short execution budget. Use ctx.waitUntil(promise) to extend execution and ensure your async work completes before the Worker is terminated. Without it, a pending fetch or database write may be cut off when the handler returns.

Multiple Cron Triggers on One Worker

All triggers call the same scheduled() handler. Use controller.cron to distinguish which schedule fired:

export default {
  async scheduled(controller, env, ctx) {
    switch (controller.cron) {
      case "*/5 * * * *":
        ctx.waitUntil(fetch("https://api.example.com/heartbeat"));
        break;
      case "0 2 * * *":
        ctx.waitUntil(runDailyCleanup(env));
        break;
      case "0 0 * * 0":
        ctx.waitUntil(generateWeeklyReport(env));
        break;
    }
  }
};

Cloudflare Cron Syntax

Cloudflare uses standard 5-field cron syntax plus Quartz-style extensions not available in Linux crontab:

* * * * *
│ │ │ │ │
│ │ │ │ └── Day of week  (0-6, Sunday=0, or SUN-SAT)
│ │ │ └──── Month        (1-12, or JAN-DEC)
│ │ └────── Day of month (1-31, supports L and W)
│ └──────── Hour         (0-23, UTC)
└────────── Minute       (0-59)
OperatorMeaningExampleAvailable in Linux?
*Any value* * * * *Yes
*/nEvery n units*/5 * * * *Yes
,Value list0 6,18 * * *Yes
-Range0 9-17 * * *Yes
LLast day of month0 0 L * *No (Quartz only)
WNearest weekday0 0 LW * *No (Quartz only)
#Nth weekday0 0 ? * 2#1No (Quartz only)

The L, W and # operators come from Quartz Scheduler and are not available in standard Linux crontab. This makes Cloudflare Workers more expressive than most other platforms for complex schedules like "last weekday of the month".

Cloudflare Cron Examples

ExpressionDescription
* * * * *Every minute
*/5 * * * *Every 5 minutes
0 * * * *Every hour
0 2 * * *Daily at 2:00 AM UTC
0 9 * * 1-5Weekdays at 9:00 AM UTC
0 0 L * *Last day of every month
59 23 LW * *Last weekday of every month at 23:59
0 0 ? * 2#1First Monday of every month

Testing Cron Triggers Locally

With wrangler dev

wrangler dev
# In another terminal:
curl "http://localhost:8787/cdn-cgi/handler/scheduled?cron=*+*+*+*+*"

Spaces in the cron expression must be URL-encoded as +. Add &time= to override the scheduled time.

Trigger a deployed Worker

wrangler crons trigger my-worker

Triggers the cron handler on the deployed Worker immediately, without waiting for the schedule.

Cloudflare Cron Trigger Plan Limits

PlanMax cron triggersNotes
Free5 per accountShared across all Workers on the account
Paid (Workers Paid)250 per accountEach trigger has its own cron expression

Build your Cloudflare cron trigger expression

Cloudflare supports standard 5-field cron plus L, W and # operators. Generate the base expression here and adjust with Cloudflare-specific operators if needed.