Cron Triggers Land on Workers
Cloudflare has rolled out Cron Triggers for its Workers serverless platform, letting developers run Worker scripts on a fixed schedule rather than only in response to HTTP requests. The feature follows the standard Unix cron pattern, making it suitable for periodic maintenance jobs, polling third-party APIs for fresh data, and similar recurring tasks. In addition to being one of the most-requested features from external developers, it has also been used internally at Cloudflare since before the public launch.
How Scheduling Reaches the Edge
Schedule definitions created through the Cloudflare API are stored as records in a central database with all the information required to execute the Worker on its given cron schedule. A separate service reads those records, continuously assesses the state of the edge network, and distributes the schedules to individual cities. From there, an edge-node service polls for schedule changes and hands them off to the Workers runtime at the appropriate time.
The distribution layer deliberately avoids dispatching a Worker to an edge node that is disabled for any reason. The same mechanism leaves room for future optimizations, such as deciding where to run a schedule based on compute cost, bandwidth, or latency.
A New Type of Worker Event
The introduction of Cron Triggers brings with it a new Worker event type, distinct from the fetch handler that web requests use. This represents a broader shift: Workers are no longer strictly bound to HTTP request/response cycles. Cloudflare expects to introduce additional non-HTTP handlers down the line, covering areas such as Worker log output or TCP-based Workers.
For now, the JavaScript API brings a dedicated handler for the scheduled event:
addEventListener('scheduled', event => {
event.waitUntil(someAsyncFunction(event))
})
The event passed to the handler is defined in TypeScript with the following interface:
interface ScheduledEvent {
type: 'scheduled';
scheduledTime: int; // milliseconds since the Unix epoch
}
Any Worker that registers a handler for this new event type can be attached to a schedule.
API Additions
The existing script upload endpoint PUT /accounts/:account_identifier/workers/scripts/:name remains unchanged, except that script validation now detects and returns the event handlers a Worker registers.
A new endpoint, PUT /accounts/:account_identifier/workers/scripts/:name/schedules, creates or replaces all schedules for a script in a single call. Any schedules not present in the request body are removed. The current constraints allow up to three distinct cron schedules per script, with a minimum interval of one minute. Cron expressions containing year fields are rejected. The corresponding GET endpoint returns the active schedules for a script.
[
{"cron": "* * * * *"},
...
]
{
"schedules": [
{
"cron": "* * * * *",
"created_on": <time>,
"modified_on": <time>
},
...
]
}
Inside the Schedule Runner
To consume the schedules and fire the Worker at the right moment, Cloudflare built a new service in Rust, deployed to edge nodes via HashiCorp Nomad. Nomad keeps the runner alive on each node and can relocate it between machines as needed. Rust was chosen for its performance and reliability, along with its native Cap'n Proto RPC support for talking to the Workers runtime. The Tokio async runtime, along with Anyhow, Clap, and Serde libraries, simplified error handling, configuration, and async behavior.
Because off-the-shelf cron parsing didn't meet the project's requirements, the team wrote a custom parser using the nom parsing library. It compiles cron expressions into values that can be checked against a given time to decide whether a schedule should fire. When a job is due, the runner sends a Cap'n Proto RPC message to the runtime, which invokes the Worker's scheduled handler instead of fetch.
Getting Started
Cron Triggers is live as of this announcement. Developers can enable it by creating a Worker and navigating to the Triggers tab in the Cloudflare dashboard.



