Cron Triggers: Automate Recurring Tasks in Cloudflare Workers
Learn how to use Cron Triggers to automate recurring tasks in Cloudflare Workers. Master scheduling syntax, the scheduled handler, and local testing.

Previously in this course, we explored queueing tasks to handle asynchronous workloads. While queues are perfect for processing events as they arrive, sometimes you need to run code on a fixed cadence—like cleaning up your D1 database or generating daily usage reports. This is where Cron Triggers come in.
Unlike traditional server-based cron systems that require a persistent machine to be running (as seen in Linux Cron Job Automation), Cloudflare Cron Triggers are serverless. They wake up your Worker at the specified time, execute your logic, and shut it down immediately after.
Understanding Cron Triggers
A Cron Trigger is a configuration that tells Cloudflare to invoke your Worker's scheduled handler at a set interval. You don't need a server to be "on" to wait for the clock; Cloudflare’s edge network handles the orchestration for you.
The scheduling syntax uses the standard five-field cron format:
*(Minute): 0-59*(Hour): 0-23*(Day of Month): 1-31*(Month): 1-12*(Day of Week): 0-6 (Sunday-Saturday)
Configuring a Scheduled Worker
To add a schedule to your project, you define it in your wrangler.toml file. This tells Cloudflare exactly when to run your code.
Open your wrangler.toml and add the following block:
TOML[triggers] crons = ["*/30 * * * *"] # Runs every 30 minutes
You can define multiple schedules by adding more strings to the crons array. This is useful if you need to run a "cleanup" task hourly and a "reporting" task once per day.
Writing the Cron Trigger Script
In your Worker code, you need to handle the scheduled event. This is distinct from the fetch event used for HTTP requests.
Modify your index.js (or index.ts) to include the scheduled handler:
JAVASCRIPTexport default { async scheduled(event, env, ctx) { switch (event.cron) { case "*/30 * * * *": await performDatabaseCleanup(env); break; default: console.log(CE9178">`Triggered unknown cron: ${event.cron}`); } }, async fetch(request, env, ctx) { return new Response("Hello from Worker!"); } }; async function performDatabaseCleanup(env) { // Example: Delete old sessions from your D1 database await env.DB.prepare("DELETE FROM sessions WHERE created_at < ?") .bind(Date.now() - 86400000) .run(); console.log("Cleanup task completed."); }
The event object provides the cron string that triggered the execution, allowing you to route logic based on the schedule if you have multiple triggers in one Worker.
Testing Scheduled Tasks
Testing cron jobs can be frustrating if you have to wait for the real clock to tick. Wrangler allows you to trigger these events manually during local development.
-
Start your dev server:
npx wrangler dev -
Trigger the event via cURL or a browser: You can simulate the scheduled event by sending a POST request to the local development URL with the
__scheduledpath:Bashcurl "http://localhost:8787/__scheduled?cron=*/30+*+*+*+*"
This forces your scheduled handler to execute immediately, allowing you to verify your logic, database queries, and logging without waiting for the actual schedule to arrive.
Common Pitfalls
- Execution Limits: Scheduled Workers have a maximum execution time (usually 30 seconds on the free tier). If your task performs heavy data processing, you may need to break it into smaller batches or use Queues to offload the work.
- Timezone Confusion: Cron triggers always run in UTC. If your application logic expects local time, you must handle the conversion inside your JavaScript code.
- Ignoring the Context: Always use
ctx.waitUntil()if you are performing asynchronous operations (like writing to R2 or D1) inside the handler. This ensures the Worker doesn't shut down before your database operation finishes.
FAQ
Can I run a cron job once a minute? No. Cloudflare Cron Triggers have a minimum interval of once per hour on the free plan, though paid plans allow for more frequent execution.
Does fetch code run when the cron triggers?
No. The scheduled handler and the fetch handler are independent entry points. Logic inside fetch will not run unless an HTTP request hits your URL.
How do I monitor if my cron job failed?
Check your Worker's logs in the Cloudflare Dashboard under "Logs" or use wrangler tail to watch the output in real-time.
Recap
We’ve successfully moved from standard HTTP-driven Workers to event-driven automation. By configuring wrangler.toml and implementing the scheduled handler, you can now automate maintenance, reporting, and background cleanup without managing external servers or infrastructure.
Up next: Handling WebSockets — we’ll learn how to establish persistent, bidirectional connections for real-time applications.
Work with me

AI Automation & Agentic Workflow Development
Automate the repetitive work eating your time — content pipelines, data workflows, and agentic AI tasks that run themselves.

Custom Email & File Storage System on Cloudflare (Google Workspace Alternative)
Your own private email + file storage suite on your domain — unlimited mailboxes, no per-seat fees. A self-owned Google Workspace alternative for a flat ~$5/month.


