Cron Triggers on Cloudflare Workers, and the 10ms problem
Cron Triggers are the fastest scheduled compute you can get, and on the free plan each invocation gets ten milliseconds of CPU. That number is the whole story.
What Cloudflare Workers gives you
Cloudflare Cron Triggers. A cron expression mapped to a Worker’s scheduled handler, running on Cloudflare’s edge in UTC.
- Timezone
- UTC
- Triggers per account (Free)
- 5
- Triggers per account (Paid)
- 250
- CPU per invocation (Free)
- 10 milliseconds
- CPU per invocation (Paid)
- 30 seconds, or 15 minutes at hourly-or-slower
- Syntax
- Five fields, with L, W and # — no seconds
Checked against Cloudflare docs on 18 August 2026. These change — if a deploy disagrees with this page, believe the deploy and tell us.
When this is the right answer
Most people reading this should keep what they have. It is worth being specific about when:
- You are on the paid plan and the work is Worker-shaped. Thirty seconds of CPU at the edge with a minute of granularity is a genuinely strong scheduler.
- The scheduled work is tiny — a cache purge, a queue nudge — and fits in the free budget.
Where it runs out
Ten milliseconds of CPU is not much
That is the free-plan budget per invocation. Waiting on a slow API does not count against CPU time, but any real parsing or crypto does, and exceeding it kills the invocation.
Five triggers per account, not per Worker
The free cap is account-wide, so a handful of side projects can exhaust it between them.
The syntax is wider than most, which travels badly
Cloudflare accepts L, W and # and names like MON. Expressions written here are not portable — the same string is rejected by Vercel outright.
Scheduling it from outside
A Worker can be invoked over HTTP as easily as on a trigger. Give it a fetch handler alongside the scheduled one and the schedule can come from outside.
One Worker, either entry point
export default {
async scheduled(event, env, ctx) {
ctx.waitUntil(doTheWork(env));
},
async fetch(request, env) {
if (request.headers.get('x-cron-secret') !== env.CRON_SECRET) {
return new Response('Unauthorized', { status: 401 });
}
await doTheWork(env);
return new Response('ok');
},
};Worth being clear: this does not raise the CPU limit — the Worker still runs under its plan’s budget. What it buys is a schedule that is not capped at five, a record of every run, and an alert when one fails.
What getNodi adds
getNodi calls a URL on a schedule and tells you what happened. Any schedule down to your plan’s floor, in your timezone rather than UTC, with retries, a record of every run — status, latency, response — and an alert the first time one fails. Credentials are encrypted at rest and requests can be HMAC-signed so your endpoint can verify they came from us.
The free plan runs 3 jobs hourly and needs no card, which is enough to find out whether this works for you. What it will not do is run a container, hold a connection open for an hour, or execute your code — it makes HTTP requests, and everything above is a way of making that enough.