AWS EventBridge Cron Expressions Guide
Everything you need to know about writing cron expressions for AWS EventBridge (formerly CloudWatch Events), including key differences from standard Unix cron.
What is AWS EventBridge?
AWS EventBridge is a serverless event bus that connects applications using events. One of its core features is the ability to create scheduled rules that trigger Lambda functions, Step Functions, or other AWS services on a recurring basis. These schedules can be defined using either cron expressions or rate expressions.
While EventBridge cron expressions look similar to standard Unix cron, there are important differences that catch developers off guard. If you have written cron expressions for Linux crontab or CI/CD platforms and are now writing them for AWS, you need to understand these differences.
EventBridge Cron Format: 6 Fields
The most immediately visible difference is that EventBridge uses a 6-field format instead of the standard 5-field format. EventBridge adds a year field at the end while keeping minutes as the finest granularity (no seconds field).
EventBridge 6-Field Format
┌───────────── minute (0-59) │ ┌───────────── hour (0-23) │ │ ┌───────────── day of month (1-31) │ │ │ ┌───────────── month (1-12 or JAN-DEC) │ │ │ │ ┌───────────── day of week (1-7 or SUN-SAT) │ │ │ │ │ ┌───────────── year (1970-2199) │ │ │ │ │ │ * * * * * *
Note: All times are in UTC. EventBridge does not support timezone configuration for cron rules.
Key Differences from Standard Unix Cron
Below are the critical differences between standard Unix cron and AWS EventBridge cron. Missing even one of these can result in schedules that fire at unexpected times or fail to create entirely.
Day of Week Numbering
This is the most common source of confusion. In standard Unix cron, Sunday is 0 (or 7). In EventBridge, Sunday is 1 and Saturday is 7.
| Day | Unix Cron | EventBridge |
|---|---|---|
| Sunday | 0 (or 7) | 1 (or SUN) |
| Monday | 1 | 2 (or MON) |
| Tuesday | 2 | 3 (or TUE) |
| Wednesday | 3 | 4 (or WED) |
| Thursday | 4 | 5 (or THU) |
| Friday | 5 | 6 (or FRI) |
| Saturday | 6 | 7 (or SAT) |
To avoid confusion, use three-letter day names (MON, TUE, WED, etc.) instead of numbers. These are case-insensitive and work identically across both systems.
The Question Mark (?) Wildcard
EventBridge requires that if you specify a value in the day-of-month field, you must use ? in the day-of-week field, and vice versa. You cannot use * in both fields simultaneously. The ? means “no specific value” and is distinct from * (every value).
# CORRECT: Day-of-month = 1, day-of-week = ? (no specific value)
cron(0 9 1 * ? *)
# CORRECT: Day-of-month = ?, day-of-week = MON-FRI
cron(0 9 ? * MON-FRI *)
# INVALID: Cannot use * in both day fields
cron(0 9 * * * *) # This will fail in EventBridgeStandard Unix cron does not have this restriction. You can freely use * in both day-of-month and day-of-week fields.
The Year Field
EventBridge supports a year field at the end of the expression. This allows you to create schedules that only fire in specific years, which is useful for one-time scheduled events or year-bounded schedules.
# Fire every day at 9 AM in 2025 only
cron(0 9 ? * * 2025)
# Fire every Monday at 9 AM from 2025 to 2027
cron(0 9 ? * MON 2025-2027)
# Fire every day at noon for all years (wildcard)
cron(0 12 ? * * *)The cron() Wrapper Syntax
When using EventBridge through the AWS Console, CLI, or CloudFormation, the cron expression must be wrapped in a cron() function call. The fields inside do not use the same quoting as Unix crontab.
# AWS CLI example
aws events put-rule \
--name "daily-9am" \
--schedule-expression "cron(0 9 ? * MON-FRI *)"
# CloudFormation / CDK
ScheduleExpression: "cron(0 9 ? * MON-FRI *)"
# Terraform
schedule_expression = "cron(0 9 ? * MON-FRI *)"EventBridge-Specific Special Characters
EventBridge supports several special characters beyond the standard *, ,, -, and /.
L (Last)
In the day-of-month field, L represents the last day of the month. Combined with a day-of-week value like FRIL, it means “the last Friday of the month.”
# Last day of every month at midnight
cron(0 0 L * ? *)
# Last Friday of every month at 5 PM
cron(0 17 ? * FRIL *)W (Weekday)
The W character in the day-of-month field specifies the nearest weekday to the given day. 15W means “the nearest weekday to the 15th.”
# Nearest weekday to the 15th of every month
cron(0 9 15W * ? *)
# Nearest weekday to the 1st of every month
cron(0 9 1W * ? *)# (Nth Occurrence)
The # character specifies the Nth occurrence of a weekday in a month. In EventBridge, MON#1 means “the first Monday of the month.”
# First Monday of every month at 10 AM
cron(0 10 ? * MON#1 *)
# Third Wednesday of every month at 2 PM
cron(0 14 ? * WED#3 *)
# Second Friday of every month at 4 PM
cron(0 16 ? * FRI#2 *)Common EventBridge Cron Examples
Here are frequently needed EventBridge schedules ready to copy into your infrastructure code.
| Expression | Description |
|---|---|
| cron(0/5 * ? * * *) | Every 5 minutes |
| cron(0 * ? * * *) | Every hour at minute 0 |
| cron(0 9 ? * MON-FRI *) | Weekdays at 9:00 AM UTC |
| cron(0 0 ? * * *) | Daily at midnight UTC |
| cron(0 12 ? * SUN *) | Every Sunday at noon UTC |
| cron(0 0 1 * ? *) | First of every month at midnight |
| cron(0 9 ? * MON#1 *) | First Monday of every month at 9 AM |
| cron(0 0 L * ? *) | Last day of every month at midnight |
| cron(0 18 ? * FRIL *) | Last Friday of every month at 6 PM |
Migration Guide: Unix Cron to EventBridge
If you are migrating existing Unix crontab schedules to AWS EventBridge, follow this step-by-step process to convert your expressions correctly.
Step 1: Adjust Day-of-Week Numbers
If your Unix cron uses numeric day-of-week values, add 1 to each value. Better yet, replace numbers with three-letter names to eliminate ambiguity.
# Unix cron: Weekdays (Monday=1 through Friday=5)
0 9 * * 1-5
# EventBridge: Weekdays (Monday=MON through Friday=FRI)
cron(0 9 ? * MON-FRI *)Step 2: Add the Question Mark
Replace one of your two day fields with ?. If you are specifying a day of week, put ? in day-of-month. If specifying a day of month, put ? in day-of-week.
# Unix cron: 1st of every month
0 0 1 * *
# EventBridge: 1st of every month (? in day-of-week)
cron(0 0 1 * ? *)Step 3: Add the Year Field
Append * as the year field unless you want to restrict the schedule to specific years.
Step 4: Wrap in cron() Syntax
Surround the full expression with cron().
Complete Migration Examples
| Unix Cron | EventBridge | Description |
|---|---|---|
| */5 * * * * | cron(0/5 * ? * * *) | Every 5 minutes |
| 0 9 * * 1-5 | cron(0 9 ? * MON-FRI *) | Weekdays at 9 AM |
| 0 0 1 * * | cron(0 0 1 * ? *) | Monthly on 1st |
| 30 4 * * * | cron(30 4 ? * * *) | Daily at 4:30 AM |
| 0 0 * * 0 | cron(0 0 ? * SUN *) | Every Sunday |
EventBridge Timezone Considerations
All EventBridge cron expressions run in UTC. There is no way to configure a timezone for a scheduled rule. If you need your schedule to fire at 9:00 AM Eastern Time, you must calculate the UTC equivalent:
- EST (UTC-5): 9:00 AM Eastern = 14:00 UTC, so use
cron(0 14 ? * MON-FRI *) - EDT (UTC-4): During daylight saving time, 9:00 AM Eastern = 13:00 UTC
For schedules that need to follow local time across daylight saving transitions, consider using AWS Step Functions with a Wait state or AWS Scheduler (which does support timezone-aware scheduling via the FlexibleTimeWindow and IANA timezone IDs).
Debugging EventBridge Schedules
When your EventBridge rule is not firing as expected, check these common issues:
- Missing
?in day fields: EventBridge rejects expressions with*in both day-of-month and day-of-week. Replace one with?. - Wrong day-of-week numbering: If your schedule fires on the wrong day, verify you are using EventBridge numbering (1=Sunday) rather than Unix numbering (0=Sunday).
- UTC vs local time: If the schedule fires at the wrong hour, confirm you have accounted for the offset between UTC and your local timezone.
- Rule is disabled: EventBridge rules can be enabled/disabled. Check the rule state in the console or via
aws events describe-rule. - Target permissions: Even if the rule fires correctly, the target (Lambda, SQS, etc.) needs the proper IAM permissions. Check CloudWatch metrics for
FailedInvocations.
EventBridge vs EventBridge Scheduler
AWS released EventBridge Scheduler as a separate service in late 2022. While EventBridge rules use the cron() syntax described above, EventBridge Scheduler adds important features:
- Timezone support: Scheduler supports IANA timezone IDs (e.g.,
America/New_York), handling daylight saving time automatically. - One-time schedules: Create a schedule that fires exactly once at a specific time using the
at()syntax. - Flexible time windows: Allow the schedule to fire within a window (e.g., between 9:00 and 9:15 AM) to reduce thundering herd problems.
- Higher throughput: Scheduler supports millions of schedules per account, compared to the 300-rule limit on EventBridge rules.
For new projects, consider using EventBridge Scheduler instead of EventBridge rules for scheduled tasks.
Test Your Expressions
Before deploying an EventBridge cron expression to production, verify it with our Cron Expression Builder. While the builder uses standard 5-field format, you can use it to validate the core schedule logic before adding the EventBridge-specific ? and year field.
For timestamp conversions in your Lambda functions and EventBridge targets, our Epoch Converter can help you work with Unix timestamps in event payloads.
Further Reading
- AWS EventBridge Scheduler — schedule types
Official AWS documentation on cron and rate schedule expressions.
- AWS EventBridge — cron expressions
EventBridge-specific cron syntax reference with required year field.
- Terraform aws_scheduler_schedule
Infrastructure-as-code resource for managing EventBridge schedules.