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 uses a 6-field cron format that differs from standard Linux cron. Understanding these differences prevents hard-to-debug production issues.
| Field | Values | Wildcards |
|---|---|---|
| Minutes | 0–59 | * , - / |
| Hours | 0–23 | * , - / |
| Day of month | 1–31 | * , - / ? L W |
| Month | 1–12 or JAN–DEC | * , - / |
| Day of week | 1–7 or SUN–SAT | * , - / ? L # |
| Year | 1970–2199 | * , - / |
? in exactly one of day-of-month or day-of-week.
EventBridge offers two schedule expression types. Choosing the right one keeps your configs readable and less error-prone.
rate(5 minutes) # Every 5 minutes rate(1 hour) # Every hour rate(7 days) # Every 7 days
rate(1 minute) not rate(1 minutes). AWS returns an error for the plural form.
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
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 ?.
| Expression | Valid? | Meaning |
|---|---|---|
cron(0 12 * * ? *) | ✗ Invalid | Both DOM and DOW are wildcards — must use ? |
cron(0 12 ? * * *) | ✓ Valid | Noon every day — DOW is wildcard, DOM is ? |
cron(0 12 15 * ? *) | ✓ Valid | Noon on the 15th — DOM specified, DOW is ? |
cron(0 12 ? * MON *) | ✓ Valid | Noon on Mondays — DOW specified, DOM is ? |
cron(0 12 15 * MON *) | ✗ Invalid | Both DOM and DOW specified — ambiguous |
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.
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"
}'
cron(0 9 15 * MON *) — Invalid. Use cron(0 9 15 * ? *) for the 15th or cron(0 9 ? * MON *) for Mondays.
cron(0 14 ? * MON-FRI *).
0 9 * * 1-5 is invalid in EventBridge. You need 6 fields and a ?: cron(0 9 ? * MON-FRI *).
1-5 means Sun–Thu, not Mon–Fri. Use named days like MON-FRI to avoid confusion.
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.* to match all years. The field order is: minutes, hours, day-of-month, month, day-of-week, year.? 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 ?.cron(30 3 ? * * *). Use CronRead Pro's timezone calculator to find the right UTC time for your timezone.cron() wrapper — CronRead Pro strips it automatically and handles the 6-field format.