Cron Jobs on AWS

A scheduled job (cron job) is a task that runs automatically at a fixed time or on a recurring interval — no incoming request triggers it. Common uses include sending digest emails, archiving old records, generating reports, polling external APIs, and running database clean-up. On AWS the canonical service for this is EventBridge Scheduler.

Overview

Scheduled jobs sit outside the normal request/response flow. Because nothing is waiting for a response, they can be slow, retried on failure, and run off-peak without affecting users. The key design concerns are:

  1. Idempotency — at-least-once delivery means a job can fire more than once for the same schedule slot (network retries, delivery guarantees). Design the job so running it twice produces the same result as running it once.
  2. Missed schedules — if the target is unavailable when the schedule fires, the invocation is lost by default. Use a dead-letter queue (DLQ) and a retry policy to capture and replay failures.
  3. Clock skew — AWS schedules are evaluated in UTC. If your cron expression encodes a business rule that depends on local time (e.g. "9 AM New York"), account for DST transitions explicitly or use a flexible time window.
  4. Overlapping runs — a long-running job started at T may still be running when the next invocation fires at T+interval. Either ensure the job completes well within the interval, or use a lock (DynamoDB conditional write, Redis SET NX) to skip the second invocation if the first is still running.

EventBridge Scheduler

EventBridge Scheduler is a dedicated AWS scheduling service (launched November 2022) that invokes a target directly — no event bus in between. It supports one-time and recurring schedules, flexible time windows, retry policies, and DLQ integration.

Core concepts

  1. Schedule — the resource you create. It holds the expression, the target, and the retry/DLQ configuration. Schedules are regional.
  2. Target — what to invoke. Supports over 270 AWS API operations directly (Lambda Invoke, ECS RunTask, Step Functions StartExecution, SQS SendMessage, SNS Publish, and more). You provide the ARN and an IAM role the scheduler assumes.
  3. Flexible time window — instead of firing at exactly T, the scheduler picks a random time within a window (e.g. within 15 minutes of T). Useful for spreading load when thousands of schedules would otherwise all fire at the same second.
  4. Retry policy — on a failed invocation, the scheduler retries up to 185 times over a configurable retention window (up to 24 hours). Configure a DLQ to capture events that exhaust all retries.
  5. Schedule groups — logical containers for organising schedules. Useful for applying tags and managing permissions at group level.

Delivery guarantee

EventBridge Scheduler provides at-least-once delivery — it may invoke the target more than once for a single schedule occurrence in rare failure scenarios. Design targets to be idempotent. For Lambda, the scheduler passes a unique scheduledEventId you can use as an idempotency key.

Cron & Rate Expressions

EventBridge Scheduler accepts two expression formats:

Rate expressions

The simplest form — fire every N units of time from when the schedule was created:

  1. rate(5 minutes) — every 5 minutes
  2. rate(1 hour) — every hour (singular unit must use singular noun)
  3. rate(7 days) — every 7 days

Cron expressions

AWS uses a 6-field cron syntax — cron(minutes hours day-of-month month day-of-week year). All times are UTC.

FieldValuesWildcards
Minutes0–59* , , , - , /
Hours0–23* , , , - , /
Day-of-month1–31* , ? , , , - , / , L , W
Month1–12 or JAN–DEC* , , , - , /
Day-of-week1–7 or SUN–SAT* , ? , , , - , / , L , #
Year1970–2199* , , , - , /

Day-of-month and day-of-week cannot both be specified — one must be ?(no specific value).

Common examples

  1. cron(0 12 * * ? *) — every day at 12:00 UTC
  2. cron(0 9 ? * MON-FRI *) — weekdays at 09:00 UTC
  3. cron(0 0 1 * ? *) — first day of every month at midnight UTC
  4. cron(0/15 * * * ? *) — every 15 minutes
  5. cron(0 18 L * ? *) — last day of every month at 18:00 UTC

Scheduler vs EventBridge Rules

Before EventBridge Scheduler existed, the standard approach was an EventBridge Rule with a Schedule source. Both still work; the rule-based approach is simpler for basic use cases already wired into an event bus.

EventBridge SchedulerEventBridge Rules (schedule)
ReleasedNovember 2022Original CloudWatch Events (2015)
One-time schedulesYesNo
Flexible time windowsYesNo
Retry policyYes (up to 185 retries, 24 h window)Limited (target-level only)
DLQ supportYes (on the schedule)Yes (on the rule target)
Supported targets270+ AWS API operations directly~20 AWS services via event bus
ScaleMillions of schedules per account300 rules per event bus (default)
Best forNew workloads, per-user schedules, one-time jobsSimple recurring tasks already in an event-driven architecture