scheduled handler of your App on a schedule. Use Cron Triggers for cleanup, digests, polls of an upstream service, and summaries.
celld, the Judt runtime, runs each occurrence one time across all of its nodes, so you don’t need a lock.
Configure
Add the schedules totriggers.crons in the wrangler.json file:
wrangler.json
triggers object has one key, crons. A Cron Trigger needs a main entry module that exports a scheduled handler. If an expression isn’t valid, then the deploy stops.
All times are UTC. To run a job at a user’s local time, convert that time to UTC. Daylight saving time doesn’t change the UTC schedule, so the job runs one hour earlier or later in local time when the clocks change. Tell the people who depend on the job about this shift.
Write a cron expression
An expression has five fields, in the following order: minute, hour, day of month, month, and day of week. The resolution is one minute. Each field accepts the following forms:*for every value- A single value
- A range,
a-b - A list,
a,b - A step,
*/nora-b/n
JAN to DEC, and days of the week accept SUN to SAT.
The day-of-month field also accepts L (the last day), L-3 (three days before the last day), LW (the last weekday), and 15W (the weekday nearest day 15). The day-of-week field accepts FRIL (the last Friday) and MON#2 (the second Monday).
celld refuses the following forms:
- Descending ranges, such as
SAT-SUN. WriteSAT,SUNinstead. - Lists that contain
*, such as1,*. - Steps larger than the field, such as
*/60in the minute field.
Handle the event
Thescheduled handler receives a controller object. If you have more than one schedule, then use controller.cron to select the job:
index.js
controller object has the following members:
cron: the expression text, exactly as it appears in thewrangler.jsonfile.scheduledTime: the scheduled minute, in milliseconds. It doesn’t change on a retry, so you can use it as the job ID.noRetry(): stops retries for this occurrence.
Retries and missed runs
celld runs scheduled handlers with the following behavior:- One node runs each occurrence.
- Handlers of one App don’t overlap. A slow run delays the next run.
- If the handler throws, then celld retries it after 4 seconds, and doubles the delay each time, for a maximum of six attempts. Retries stop at the next occurrence. A restart removes a pending retry.
- After downtime, only the last missed occurrence runs.
last_processed_at value, in D1 or KV. In each run, process the records from that mark to scheduledTime, and then advance the mark.
Keep the handler short
We recommend that the cron handler start the work and leave the slow parts to other features. Use the following patterns:- For many records or slow calls, let the handler select IDs and send them to a queue. For more information, see Queues.
- For processes with many steps or long waits, start a Workflow from the handler. For more information, see Workflows.
- For a timer that belongs to one object, use a Durable Object alarm or a queue message with
delaySecondsinstead of a Cron Trigger. For more information, see Durable Objects.
Test a scheduled job
The dev server runs Cron Triggers on their schedule, but you can’t start one manually. To test a job, put it in a function, and call that function from a temporary route:index.js
Limits
The following table lists the limits of Cron Triggers:Differences from Cloudflare
Keep the following celld behavior in mind when you port a Cron Trigger from Cloudflare:- The only configuration key is
triggers.crons. - After downtime, only the last missed occurrence runs. If you need every interval, keep a high-water mark.
- A restart of celld removes a pending retry.
- The dev server has no way to start a Cron Trigger manually. Call the job function from a temporary route.