Skip to content

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

Five fields, in UTC

Cloudflare's examples

Weekdays
For local and Nitro dev times
Comma-separated

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 * * SUN

The next runs appear once the page has loaded.

The blocks below use the spelling both read the same way.

Wrangler file
wrangler.jsonc
{
  "triggers": {
    "crons": ["0 9 * * SUN"]
  }
}
nuxt.config.ts, Nuxt 4
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.

Fire it in wrangler dev
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.

Run the first task in nuxt dev
curl "http://localhost:3000/_nitro/tasks/db:cleanup"

Nitro's dev server runs a task by name on request, without waiting for its schedule.

Everything runs in this tab with croner, and nothing is sent. The expression, the task names and a time zone you pick go in the address, so a link opens the same 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:

  • L in the day-of-month field is the last day of the month, and LW the last weekday, Monday to Friday. After a weekday, as in FRIL or 6L, it means the last Friday.
  • W after a date, as in 15W, is the weekday nearest the 15th, without crossing into another month.
  • # picks the nth weekday of the month: MON#1 is 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

DigitCloudflarecroner, Nitro devUnix cron
0RefusedSunSun
1SunMonMon
2MonTueTue
3TueWedWed
4WedThuThu
5ThuFriFri
6FriSatSat
7SatSunSun

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

ExpressionRuns, 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-FRIMonday to Friday at 08:30
0 9 * * MONEvery 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#1The 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

Cloudflare Cron Triggers
ItemRateSource
Cron Triggers, Workers Free 5 per accountdevelopers.cloudflare.com
Cron Triggers, Workers Paid 250 per accountdevelopers.cloudflare.com
CPU per run, Workers Free 10 millisecondsdevelopers.cloudflare.com
CPU per run, Workers Paid, under an hour apart 30 secondsdevelopers.cloudflare.com
CPU per run, Workers Paid, an hour or more apart 15 minutesdevelopers.cloudflare.com
Wall time per run 15 minutesdevelopers.cloudflare.com
A trigger change reaching the network Up to 15 minutesdevelopers.cloudflare.com
Past runs in the dashboard's Cron Events The latest 100developers.cloudflare.com
What each run is billed as As in Cloudflare's pricing example for an hourly trigger1 request, plus its CPU timedevelopers.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

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.

See what Nuxter includesFrom $249, one-time.