AWS GUIDE

AWS EventBridge
Cron Expression Examples

20+ real-world EventBridge schedule examples with Terraform, AWS CDK, and CLI snippets. Covers cron() vs rate(), the ? wildcard, common mistakes, and production patterns.

AWS EventBridge Cron Format

AWS EventBridge uses a 6-field cron format that differs from standard Linux cron. Understanding these differences prevents hard-to-debug production issues.

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* , - /
⚠ Key difference from Linux cron: In AWS EventBridge, day-of-week numbering starts at 1 (Sunday=1) not 0. And you must use ? in exactly one of day-of-month or day-of-week.

cron() vs rate()

EventBridge offers two schedule expression types. Choosing the right one keeps your configs readable and less error-prone.

Use rate() for simple intervals

rate(5 minutes)    # Every 5 minutes
rate(1 hour)       # Every hour
rate(7 days)       # Every 7 days
⚠ rate() quirk: Use singular for value 1: rate(1 minute) not rate(1 minutes). AWS returns an error for the plural form.

Use cron() for precise scheduling

cron(0 9 ? * MON-FRI *)     # 9 AM UTC on weekdays
cron(0 0 1 * ? *)            # Midnight on the 1st of every month
cron(30 14 ? * MON#2 *)     # 2:30 PM on the 2nd Monday of each month

The ? Wildcard Explained

This trips up more developers than anything else in EventBridge cron. The ? means "no specific value" — and exactly one of day-of-month or day-of-week must always be ?.

ExpressionValid?Meaning
cron(0 12 * * ? *)✗ InvalidBoth DOM and DOW are wildcards — must use ?
cron(0 12 ? * * *)✓ ValidNoon every day — DOW is wildcard, DOM is ?
cron(0 12 15 * ? *)✓ ValidNoon on the 15th — DOM specified, DOW is ?
cron(0 12 ? * MON *)✓ ValidNoon on Mondays — DOW specified, DOM is ?
cron(0 12 15 * MON *)✗ InvalidBoth DOM and DOW specified — ambiguous

20+ EventBridge Cron Examples

Every N minutes / hours

Every 5 minutes
cron(0/5 * ? * * *)
Runs at :00, :05, :10, :15... — use for health checks, polling
Every 15 minutes
cron(0/15 * ? * * *)
Common for near-real-time data syncs
Every hour on the hour
cron(0 * ? * * *)
Hourly aggregations, cache warming
Every 6 hours
cron(0 0/6 ? * * *)
Runs at midnight, 6 AM, noon, 6 PM UTC

Daily schedules

Daily at midnight UTC
cron(0 0 ? * * *)
Daily database cleanup, report generation
Daily at 9 AM UTC
cron(0 9 ? * * *)
Morning digest emails, daily summaries
Daily at 2:30 AM UTC
cron(30 2 ? * * *)
Off-hours maintenance window, low-traffic period
Twice daily — 8 AM and 8 PM UTC
cron(0 8,20 ? * * *)
Twice-daily sync jobs, morning and evening digests

Weekday schedules

Weekdays at 9 AM UTC (Mon–Fri)
cron(0 9 ? * MON-FRI *)
Business hours jobs, weekday-only processing
Weekdays every 30 minutes, 9 AM–5 PM
cron(0/30 9-17 ? * MON-FRI *)
Business hours polling, order processing windows
Monday mornings at 8 AM
cron(0 8 ? * MON *)
Weekly kickoff jobs, Monday report generation
Friday afternoons at 5 PM UTC
cron(0 17 ? * FRI *)
End-of-week reports, weekly archiving

Monthly schedules

1st of every month at midnight
cron(0 0 1 * ? *)
Monthly billing, subscription renewals
Last day of month
cron(0 23 L * ? *)
Month-end closing jobs — L means last day
1st and 15th of month
cron(0 9 1,15 * ? *)
Semi-monthly payroll runs, bi-monthly reports

Nth-weekday of month

Second Monday of every month at 10 AM
cron(0 10 ? * MON#2 *)
Team meetings, monthly reviews — # means nth occurrence
First Friday of every month
cron(0 9 ? * FRI#1 *)
Monthly deployment windows, release Fridays
Last Friday of every month
cron(0 17 ? * FRI L *)
Month-end close, last-Friday-of-month jobs

Quarterly / yearly

Quarterly — first day of Jan, Apr, Jul, Oct
cron(0 0 1 1,4,7,10 ? *)
Quarterly reports, billing cycles
Once a year — January 1st at midnight
cron(0 0 1 1 ? *)
Annual resets, yearly archiving
Specific year — Dec 31 2026 only
cron(59 23 31 12 ? 2026)
One-off future events — use specific year field

Terraform Example

Here's a complete Terraform configuration for an EventBridge rule that triggers a Lambda function on a weekday schedule:

resource "aws_cloudwatch_event_rule" "weekday_job" {
  name                = "weekday-morning-job"
  description         = "Fires at 9 AM UTC Monday through Friday"
  schedule_expression = "cron(0 9 ? * MON-FRI *)"
  state               = "ENABLED"
}

resource "aws_cloudwatch_event_target" "lambda_target" {
  rule      = aws_cloudwatch_event_rule.weekday_job.name
  target_id = "WeekdayLambda"
  arn       = aws_lambda_function.my_function.arn
}

resource "aws_lambda_permission" "allow_eventbridge" {
  statement_id  = "AllowEventBridgeInvoke"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.my_function.function_name
  principal     = "events.amazonaws.com"
  source_arn    = aws_cloudwatch_event_rule.weekday_job.arn
}

Paste any cron into CronRead to instantly generate this Terraform snippet for your exact schedule.


EventBridge Scheduler (New API)

AWS introduced EventBridge Scheduler in 2022 as a more capable replacement for EventBridge Rules for scheduled invocations. Key differences:

aws scheduler create-schedule \
  --name "weekday-morning-job" \
  --schedule-expression "cron(0 9 ? * MON-FRI *)" \
  --schedule-expression-timezone "America/New_York" \
  --flexible-time-window '{"Mode": "OFF"}' \
  --target '{
    "Arn": "arn:aws:lambda:us-east-1:123456789:function:my-function",
    "RoleArn": "arn:aws:iam::123456789:role/scheduler-role"
  }'

Common Mistakes

Mistake 1: Both day-of-month and day-of-week specified
cron(0 9 15 * MON *) — Invalid. Use cron(0 9 15 * ? *) for the 15th or cron(0 9 ? * MON *) for Mondays.
Mistake 2: Forgetting UTC
EventBridge runs in UTC. For 9 AM New York time (EST = UTC-5), use cron(0 14 ? * MON-FRI *).
Mistake 3: Using 5-field Linux cron directly
0 9 * * 1-5 is invalid in EventBridge. You need 6 fields and a ?: cron(0 9 ? * MON-FRI *).
Mistake 4: Day-of-week numbering
In EventBridge, Sunday = 1 (not 0 as in Linux cron). So 1-5 means Sun–Thu, not Mon–Fri. Use named days like MON-FRI to avoid confusion.

Frequently Asked Questions

What is the difference between cron() and rate() in AWS EventBridge?
rate() defines a fixed interval — rate(5 minutes), rate(1 hour). cron() uses a 6-field expression for exact scheduling. Use rate() for simple repeating intervals; use cron() when you need to control the exact time, day, or month a rule fires.
Why does AWS EventBridge use 6 fields?
AWS adds a Year field as the 6th field. This allows you to schedule one-time events at a specific year, or use * to match all years. The field order is: minutes, hours, day-of-month, month, day-of-week, year.
What does ? mean in AWS EventBridge cron?
? means "no specific value". You must put ? in either day-of-month or day-of-week (but not both). If you're scheduling by day-of-week (MON-FRI), day-of-month must be ?. If scheduling by day-of-month (15), day-of-week must be ?.
Why is my EventBridge rule not firing at the expected time?
Most likely a UTC offset issue. EventBridge runs all schedules in UTC. If you're in UTC+5:30 (IST) and want 9 AM local time, the UTC time is 3:30 AM — so you'd use cron(30 3 ? * * *). Use CronRead Pro's timezone calculator to find the right UTC time for your timezone.
Can I paste an EventBridge cron() expression into CronRead Pro?
Yes. Paste the full expression including the cron() wrapper — CronRead Pro strips it automatically and handles the 6-field format.
⚡ Validate Your EventBridge Cron

🔧 Other Free Developer Tools

⏱ Cron Generator 🕐 Timestamp Converter 🔑 JWT Decoder 📄 YAML ↔ JSON 🔤 Base64 Encoder 🗄 SQL Explainer