DEV Community

ANKUSH CHOUDHARY JOHAL
ANKUSH CHOUDHARY JOHAL

Posted on • Originally published at johal.in

Build a Serverless Cron Job System with Cloudflare Workers 3, DynamoDB 2026, and Sentry 7

Build a Serverless Cron Job System with Cloudflare Workers 3, DynamoDB 2026, and Sentry 7

Serverless cron jobs eliminate the need to manage dedicated servers for scheduled task execution, offering automatic scaling, reduced operational overhead, and pay-per-use pricing. This guide walks through building a fully serverless cron job system using Cloudflare Workers 3 for compute, DynamoDB 2026 for persistent job storage, and Sentry 7 for error monitoring and performance tracking.

Prerequisites

  • Cloudflare account with Workers 3 enabled
  • AWS account with DynamoDB 2026 access (IAM user with read/write permissions to a dedicated cron job table)
  • Sentry 7 account with a Cloudflare Workers project configured
  • Node.js 22+ and Wrangler 3 CLI installed locally

Step 1: Initialize Cloudflare Workers Project

Start by creating a new Cloudflare Workers project using Wrangler:

wrangler init serverless-cron-system
cd serverless-cron-system
Enter fullscreen mode Exit fullscreen mode

Update wrangler.toml to enable Cron Triggers and set up environment variables for AWS and Sentry credentials:

name = "serverless-cron-system"
main = "src/index.js"
compatibility_date = "2026-01-01"
cron = ["* * * * *"] # Run every minute to check for pending jobs

[vars]
DYNAMODB_TABLE_NAME = "cron-jobs-2026"

[secrets]
AWS_ACCESS_KEY_ID = "your-aws-access-key"
AWS_SECRET_ACCESS_KEY = "your-aws-secret-key"
SENTRY_DSN = "your-sentry-dsn"
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure DynamoDB 2026 Table

Create a DynamoDB 2026 table named cron-jobs-2026 with the following schema:

  • jobId (String, Primary Key): Unique identifier for each cron job
  • schedule (String): Cron expression defining job execution frequency (e.g., 0 0 * * * for daily midnight runs)
  • payload (Map): Arbitrary data to pass to the job executor
  • lastRunAt (Number, Optional): Unix timestamp of the last successful execution
  • status (String): Current state of the job (active, paused, failed)
  • nextRunAt (Number): Precomputed Unix timestamp of the next scheduled execution

Install the AWS SDK 2026 for JavaScript to interact with DynamoDB from Workers:

npm install @aws-sdk/client-dynamodb-2026 @aws-sdk/lib-dynamodb-2026
Enter fullscreen mode Exit fullscreen mode

Step 3: Implement Cron Job Logic

Create the main worker logic in src/index.js to fetch pending jobs from DynamoDB, execute them, and update their status:

import { DynamoDBClient } from "@aws-sdk/client-dynamodb-2026";
import { DynamoDBDocumentClient, ScanCommand, UpdateCommand } from "@aws-sdk/lib-dynamodb-2026";
import * as Sentry from "@sentry/cloudflare-7";

// Initialize Sentry 7
Sentry.init({
  dsn: "SENTRY_DSN",
  environment: "production",
  release: "serverless-cron-system@1.0.0",
});

// Initialize DynamoDB client
const dynamoClient = new DynamoDBClient({
  region: "us-east-1",
  credentials: {
    accessKeyId: "AWS_ACCESS_KEY_ID",
    secretAccessKey: "AWS_SECRET_ACCESS_KEY",
  },
});
const docClient = DynamoDBDocumentClient.from(dynamoClient);

export default {
  async scheduled(event, env, ctx) {
    try {
      const now = Math.floor(Date.now() / 1000);

      // Fetch all active jobs with nextRunAt <= now
      const scanCommand = new ScanCommand({
        TableName: env.DYNAMODB_TABLE_NAME,
        FilterExpression: "#status = :active AND nextRunAt <= :now",
        ExpressionAttributeNames: { "#status": "status" },
        ExpressionAttributeValues: { ":active": "active", ":now": now },
      });

      const { Items: jobs } = await docClient.send(scanCommand);

      // Execute each pending job
      for (const job of jobs) {
        ctx.waitUntil(
          executeJob(job, env)
            .then(() => updateJobStatus(job.jobId, now, env))
            .catch((error) => {
              Sentry.captureException(error, { tags: { jobId: job.jobId } });
              updateJobStatus(job.jobId, now, env, "failed");
            })
        );
      }
    } catch (error) {
      Sentry.captureException(error);
    }
  },
};

async function executeJob(job, env) {
  // Add custom job execution logic here (e.g., send email, call API)
  console.log(`Executing job ${job.jobId} with payload:`, job.payload);
  // Simulate async work
  await new Promise((resolve) => setTimeout(resolve, 1000));
}

async function updateJobStatus(jobId, lastRunAt, env, status = "active") {
  const nextRunAt = computeNextRun(jobId); // Implement cron parser logic
  const updateCommand = new UpdateCommand({
    TableName: env.DYNAMODB_TABLE_NAME,
    Key: { jobId },
    UpdateExpression: "SET lastRunAt = :lastRun, #status = :status, nextRunAt = :nextRun",
    ExpressionAttributeNames: { "#status": "status" },
    ExpressionAttributeValues: {
      ":lastRun": lastRunAt,
      ":status": status,
      ":nextRun": nextRunAt,
    },
  });
  await docClient.send(updateCommand);
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Integrate Sentry 7

Install the Sentry 7 Cloudflare Workers SDK:

npm install @sentry/cloudflare-7
Enter fullscreen mode Exit fullscreen mode

The Sentry initialization is already included in the worker code above. Sentry 7 will automatically capture unhandled exceptions, track job execution performance, and send alerts for failed jobs. Configure Sentry dashboards to monitor:

  • Job execution success/failure rates
  • Average job execution duration
  • Worker invocation frequency

Step 5: Test the System

Add a test cron job to DynamoDB 2026 using the AWS CLI:

aws dynamodb put-item \
  --table-name cron-jobs-2026 \
  --item '{
    "jobId": {"S": "test-job-1"},
    "schedule": {"S": "* * * * *"},
    "payload": {"M": {"message": {"S": "Hello from serverless cron!"}}},
    "status": {"S": "active"},
    "nextRunAt": {"N": "'$(date +%s)'"}
  }'
Enter fullscreen mode Exit fullscreen mode

Trigger a local test of the worker using Wrangler:

wrangler dev --test-scheduled
Enter fullscreen mode Exit fullscreen mode

Check Sentry 7 for captured events and verify job execution logs in the Cloudflare Workers dashboard.

Step 6: Deploy and Monitor

Deploy the worker to Cloudflare Workers 3:

wrangler deploy
Enter fullscreen mode Exit fullscreen mode

Cloudflare will automatically run the worker every minute per the cron trigger in wrangler.toml. Use Sentry 7's alerting features to notify your team via Slack or email when jobs fail, and DynamoDB 2026's built-in monitoring to track table throughput and storage usage.

Conclusion

This serverless cron job system combines the low-latency compute of Cloudflare Workers 3, the scalable storage of DynamoDB 2026, and the robust monitoring of Sentry 7 to deliver a reliable, maintenance-free scheduled task platform. Extend the system by adding support for one-off jobs, job retries, or a REST API for managing cron jobs via DynamoDB.

Top comments (0)