Cloudflare Cron Triggers Generator and Tester
Build and test Cloudflare Cron Triggers: plain-English meaning, the next runs in UTC and your time zone, and the Wrangler and Nitro scheduledTasks config.
- Runs in your browser
Checked
01Tool
Tool
Cloudflare's examples
On Cloudflare, in UTC
At 09:00, on Sunday
In Nitro's dev scheduler, in UTC
At 09:00, on Monday
Spell it this way and both read the same schedule:
0 9 * * SUNThe next runs appear once the page has loaded.
The blocks below use the spelling both read the same way.
{
"triggers": {
"crons": ["0 9 * * SUN"]
}
}export default defineNuxtConfig({
nitro: {
experimental: { tasks: true },
scheduledTasks: {
'0 9 * * SUN': ['db:cleanup'],
},
},
})On Cloudflare, Nitro 2 runs the tasks whose key equals the cron Cloudflare sends, character for character, so keep this key and the Wrangler entry identical.
curl "http://localhost:8787/cdn-cgi/local/scheduled?cron=0+9+*+*+SUN&format=json"After nuxt build, start wrangler dev and call this. Its cron has to match a scheduledTasks key, or Nitro runs nothing.
curl "http://localhost:3000/_nitro/tasks/db:cleanup"Nitro's dev server runs a task by name on request, without waiting for its schedule.
02Guide
How it works
Cloudflare's cron dialect
A Cron Trigger is five fields: minute, hour, day of month, month and weekday, always in UTC. Each field takes *, lists with commas, ranges with hyphens and steps with slashes. Months and weekdays also take three-letter names in any case, such as jan or FRI.
Cloudflare adds three extensions borrowed from the Quartz scheduler:
Lin the day-of-month field is the last day of the month, andLWthe last weekday, Monday to Friday. After a weekday, as inFRILor6L, it means the last Friday.Wafter a date, as in15W, is the weekday nearest the 15th, without crossing into another month.#picks the nth weekday of the month:MON#1is the first Monday.
There is no seconds field, no ? and no shortcut such as @daily. Cloudflare's parser, saffron, reads L and W only as capitals. When both day fields are set, as in 0 9 1 * MON, the trigger runs on the 1st and on every Monday, not only on a Monday that falls on the 1st. saffron and croner both join the two fields with OR, the rule Unix cron documents too.
The weekday trap
| Digit | Cloudflare | croner, Nitro dev | Unix cron |
|---|---|---|---|
0 | Refused | Sun | Sun |
1 | Sun | Mon | Mon |
2 | Mon | Tue | Tue |
3 | Tue | Wed | Wed |
4 | Wed | Thu | Thu |
5 | Thu | Fri | Fri |
6 | Fri | Sat | Sat |
7 | Sat | Sun | Sun |
Cloudflare counts weekdays the way Quartz does, from 1 for Sunday. Unix cron and croner count from 0 for Sunday and accept 7 as Sunday again. A line copied from a crontab therefore runs a day early on Cloudflare, and a line written for Cloudflare runs a day late in nuxt dev. The names SUN to SAT mean the same day everywhere, so the tool rewrites every weekday digit it finds as a name.
Nitro scheduled tasks on Workers
Nuxt 4 runs on Nitro 2, where tasks sit behind experimental.tasks. nitro.scheduledTasks maps a cron string to the tasks it runs. On Cloudflare, triggers.crons in the Wrangler file decides when the Worker wakes. Nitro's scheduled handler then takes the cron that fired, controller.cron, and runs the tasks whose key is that exact string. A key that differs by one character, even MON against 2, runs nothing in production and raises no error.
nuxt dev has no Cloudflare scheduler, so Nitro runs the same keys with croner on your machine's clock. That is where both traps show up: croner reads weekday digits from 0 for Sunday, and it schedules in your local time zone rather than UTC.
Nitro v3, which arrives with Nuxt 5, writes the Wrangler triggers from scheduledTasks at build time, so the copy goes away. On Nuxt 4, keep the two lists identical, or generate one from the other.
Test a trigger before you deploy
nuxt dev runs Nitro in Node rather than in workerd, so it has no /cdn-cgi/local/scheduled route and never calls the Worker's scheduled handler. The route comes from wrangler dev and the Cloudflare Vite plugin, which is why the tool's curl command runs against the built Worker. Under the Vite plugin, swap 8787 for the Vite port, 5173 by default.
Besides cron, the route reads time, which sets controller.scheduledTime in milliseconds since the epoch, and format: with format=json it returns the handler's outcome and whether it called controller.noRetry().
Once deployed, the Worker's Cron Events page in the dashboard lists recent runs, and Workers Logs keeps them for longer.
Common schedules
| Expression | Runs, in UTC |
|---|---|
*/5 * * * * | Every 5 minutes |
0 * * * * | Every hour, on the hour |
0 */6 * * * | At 00:00, 06:00, 12:00 and 18:00 |
0 3 * * * | Every day at 03:00 |
30 8 * * MON-FRI | Monday to Friday at 08:30 |
0 9 * * MON | Every Monday at 09:00 |
0 0 1 * * | The 1st of every month at 00:00 |
0 0 L * * | The last day of every month at 00:00 |
59 23 LW * * | The last weekday of every month at 23:59 |
0 18 * * FRI#1 | The first Friday of every month at 18:00 |
0 0 1 JAN * | 1 January at 00:00 |
Paste any of them into the tool to see the next runs in your own time zone.
03Rates
The numbers it uses
| Item | Rate | Source |
|---|---|---|
| Cron Triggers, Workers Free | 5 per account | developers.cloudflare.com |
| Cron Triggers, Workers Paid | 250 per account | developers.cloudflare.com |
| CPU per run, Workers Free | 10 milliseconds | developers.cloudflare.com |
| CPU per run, Workers Paid, under an hour apart | 30 seconds | developers.cloudflare.com |
| CPU per run, Workers Paid, an hour or more apart | 15 minutes | developers.cloudflare.com |
| Wall time per run | 15 minutes | developers.cloudflare.com |
| A trigger change reaching the network | Up to 15 minutes | developers.cloudflare.com |
| Past runs in the dashboard's Cron Events | The latest 100 | developers.cloudflare.com |
| What each run is billed as As in Cloudflare's pricing example for an hourly trigger | 1 request, plus its CPU time | developers.cloudflare.com |
04Questions
Questions
- What does 0 9 * * 1 mean on Cloudflare?
- It runs at 09:00 UTC every Sunday. Cloudflare numbers weekdays from 1 for Sunday to 7 for Saturday, while Unix cron and croner read the same line as Monday. Write 0 9 * * SUN or 0 9 * * MON and every scheduler agrees on the day.
- Can Cloudflare Cron Triggers run in my time zone?
- No. Cron Triggers run in UTC and the expression has no zone setting, so convert your local time to UTC before you write it. Where clocks change for daylight saving, a trigger fixed in UTC moves by an hour against local time twice a year. The run table on this page shows each run in UTC and in your zone side by side.
- How many cron triggers can I have on Cloudflare?
- Cloudflare caps Cron Triggers per account, not per Worker, with a far higher cap on Workers Paid than on Workers Free. Each expression in a Worker's triggers.crons list is one trigger. The numbers table on this page lists both caps, read from Cloudflare's limits page.
- Why does my Nitro task run on a different day locally?
- In development, Nitro runs scheduledTasks with croner, which counts weekdays from 0 for Sunday and schedules in your machine's time zone. Cloudflare counts from 1 for Sunday and runs in UTC, so a weekday digit lands a day later in nuxt dev and the hour moves by your UTC offset. Weekday names such as MON read the same in both, which is why this page rewrites digits as names.
- How do I test a Cloudflare cron trigger locally?
- Run wrangler dev, or the Cloudflare Vite plugin, and request /cdn-cgi/local/scheduled with the expression in a cron query parameter, each space written as a plus sign. Add format=json to get the handler's outcome back as JSON. For a Nuxt app, build first, and pass a cron that equals one of your scheduledTasks keys, or Nitro runs no task.
- Does Cloudflare support a seconds field in cron expressions?
- No. Cron Triggers take five fields, from minute to weekday, so the finest schedule is once a minute. A six-field expression from Quartz or croner starts with seconds, and it has to lose that field before Cloudflare will take it.
05Sources
Sources
Every fact on this page was read from these pages on .
- Cloudflare Workers docs, Cron Triggersdevelopers.cloudflare.com/
workers/ configuration/ cron-triggers/ - Cloudflare Workers docs, Limitsdevelopers.cloudflare.com/
workers/ platform/ limits/ - Cloudflare Workers docs, Pricingdevelopers.cloudflare.com/
workers/ platform/ pricing/ - saffron, the cron parser behind Cron Triggersgithub.com/
cloudflare/ saffron - Nitro 2 docs, Tasksv2.nitro.build/
guide/ tasks - Nitro docs, Tasksnitro.build/
docs/ tasks - croner on GitHubgithub.com/
Hexagon/ croner - crontab(5), Linux manual pageman7.org/
linux/ man-pages/ man5/ crontab.5.html - Nuxt docs, Roadmapnuxt.com/
docs/ 4.x/ community/ roadmap - Nuxt docs, nuxt devnuxt.com/
docs/ 4.x/ api/ commands/ dev
Found something out of date? Tell us.
Nuxter
Building a SaaS on Nuxt?
Nuxter reads the crons in wrangler.jsonc and builds Nitro's scheduledTasks from them, so the key Nitro looks up always matches the cron Cloudflare sends. Its clean-up jobs, such as pruning expired sessions, run as Nitro tasks on that trigger.