Back to Blog
Lesson 43 of the Cloudflare: Cloudflare for Developers: DNS to CDN course
Cloud NativeAugust 21, 20264 min read

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.

CloudflareWorkersCronAutomationServerlessDevOps
Two engineers collaborating on machinery maintenance in a dimly lit industrial plant.

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:

JAVASCRIPT
export 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.

  1. Start your dev server: npx wrangler dev

  2. 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 __scheduled path:

    Bash
    curl "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.

Similar Posts