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)
| Operator | Meaning | Example | Available in Linux? |
|---|---|---|---|
* | Any value | * * * * * | Yes |
*/n | Every n units | */5 * * * * | Yes |
, | Value list | 0 6,18 * * * | Yes |
- | Range | 0 9-17 * * * | Yes |
L | Last day of month | 0 0 L * * | No (Quartz only) |
W | Nearest weekday | 0 0 LW * * | No (Quartz only) |
# | Nth weekday | 0 0 ? * 2#1 | No (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
| Expression | Description |
|---|---|
* * * * * | Every minute |
*/5 * * * * | Every 5 minutes |
0 * * * * | Every hour |
0 2 * * * | Daily at 2:00 AM UTC |
0 9 * * 1-5 | Weekdays 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#1 | First 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
| Plan | Max cron triggers | Notes |
|---|---|---|
| Free | 5 per account | Shared across all Workers on the account |
| Paid (Workers Paid) | 250 per account | Each 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.