AWS EventBridge Cron Expression Generator — 6-Field Schedule Builder

AWS EventBridge Cron Expression Generator

Build a valid 6-field EventBridge cron expression, enforce the day-of-month / day-of-week rule AWS actually requires, and see exactly what the schedule means in plain English.

Schedule fields

Generated expression

cron()

Field reference

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

Day-of-month and day-of-week each accept a few special AWS-only letters too: L (last), W (nearest weekday) on day-of-month, and L / # (nth weekday) on day-of-week. This generator validates the common range/list/step syntax; those special letters are accepted as literal text and passed through.

How to use this tool

  1. Pick a mode: Every day, By day of week, or By day of month. The tool locks the field you are not using to ? for you, because AWS rejects any expression that does not do this.
  2. Fill in minutes, hours, month and year. All six fields are validated as you type, against the actual ranges EventBridge accepts.
  3. Read the plain-English line under the expression to confirm the schedule says what you think it says — this catches most of the “works but fires at the wrong time” mistakes.
  4. Need full control? Check Advanced to edit day-of-month and day-of-week directly. The validator still enforces the AWS rule and tells you exactly which field to fix.
  5. Copy the finished cron(...) expression into your EventBridge (or CloudWatch Events) rule’s schedule expression field.

EventBridge (and its predecessor, CloudWatch Events) does not use standard five-field Unix cron. It uses six fields — minutes hours day-of-month month day-of-week year — and that sixth field, year, is the easy part. The rule that actually trips people up is the interaction between day-of-month and day-of-week: AWS requires that exactly one of those two fields be a question mark, ?. You cannot leave both as *, and you cannot put a real value in both. Try either and the rule fails validation with an error that does not always make it obvious which field is the problem.

The reasoning behind the restriction is that day-of-month and day-of-week describe overlapping, sometimes contradictory, ideas of “which day.” Standard cron resolves the ambiguity with an OR — if both fields are restricted, the job runs when either condition is true, which is rarely what anyone actually wants and is a frequent source of cron bugs on Linux. AWS closed that ambiguity off entirely: pick one axis to schedule on, and mark the other as “don’t care” with ?. A schedule that only cares about time of day, with no day restriction at all, uses * for day-of-month and ? for day-of-week — the * here means “every day,” and it still has to pair with a ? on the other field to satisfy the rule.

Day-of-week uses its own numbering, which is a second common gotcha: 1 is Sunday and 7 is Saturday. That is neither the Unix cron convention (0-6, Sunday is 0) nor the systemd convention (Monday-first). If you are porting a schedule from a Linux crontab, do not reuse the day-of-week digits directly — use the three-letter names (SUNSAT) instead, or shift the numbers by one and double-check against the reference table above.

All EventBridge schedule expressions run in UTC. There is no per-rule time zone setting on the classic cron() schedule expression (EventBridge Scheduler, the newer standalone service, does support a time zone parameter, but rules created directly on an EventBridge bus do not). If a job needs to fire at a fixed local wall-clock time across a daylight-saving transition, you either recompute the UTC offset manually twice a year or move the schedule to EventBridge Scheduler.

EventBridge also supports a small set of extra letters beyond plain numbers and lists: L for “last” (last day of the month, or last given weekday of the month), W for “nearest weekday” on day-of-month, and # on day-of-week for “the Nth occurrence” (for example 3#2 means the second Tuesday). This generator accepts and passes those through as literal text rather than fully validating their internal syntax, since they are used far less often than plain ranges, lists and steps.

Frequently asked questions

Why does AWS reject my cron expression with both day fields set?

Because EventBridge requires exactly one of day-of-month and day-of-week to be ?. Setting both to a real value (or both to *) is rejected outright. Decide which axis actually matters for your schedule, put your value there, and set the other field to ?.

What does the day-of-week number 1 mean in EventBridge?

Sunday. EventBridge numbers day-of-week 1 through 7 with 1 as Sunday and 7 as Saturday. This is different from standard Unix cron (0-6, Sunday is 0) and different again from systemd’s Monday-first convention, so a schedule copied from either of those systems needs its day-of-week field re-checked, not just re-typed.

Can I set an EventBridge schedule to run in my local time zone?

Not with a rule created directly on an EventBridge bus using cron() or rate() — those always run in UTC with no time zone option. If you need a fixed local time that survives daylight saving changes automatically, use EventBridge Scheduler instead, which supports a ScheduleExpressionTimezone parameter.

What is the difference between cron() and rate() expressions?

rate() is for simple fixed intervals, like rate(5 minutes) or rate(1 day), and does not use the six-field syntax at all. cron() is for calendar-based schedules — a specific time, specific weekday, specific day of month, and so on. Use rate() when “every N minutes/hours/days” is all you need; it is simpler and has no day-of-month/day-of-week rule to satisfy.

Does the year field default to anything if I leave it out?

No, EventBridge cron expressions always require all six fields; there is no five-field form. If you don’t care about the year, set it to * — that is what most schedules use, since restricting by year is only useful for one-off or time-boxed rules.