All topics
Topic hub

Cron expressions

How cron syntax works, and the gotchas that trip people up

A standard cron expression has five fields, in order: minute (0-59), hour (0-23), day of month (1-31), month (1-12), and day of week (0-6, where both 0 and 7 usually mean Sunday depending on the implementation). Each field accepts a literal value, a wildcard `*` for "every," a range like `1-5`, a list like `MON,WED,FRI`, or a step like `*/15` for "every 15 units starting from the field's minimum." So `*/15 * * * *` runs at :00, :15, :30, and :45 of every hour — not "every 15 minutes from whenever the schedule was created."

The field people get wrong most often is the interaction between day-of-month and day-of-week: in standard cron, if BOTH fields are restricted (neither is `*`), the schedule fires when EITHER condition is true, not when both are — an OR, not an AND. So `0 0 15 * MON` doesn't mean "the 15th, if it's a Monday"; it means "every 15th of the month, AND every Monday."

Not all cron dialects are identical. Quartz (common in Java scheduling frameworks) adds a seconds field and a year field, uses 1-7 for day-of-week starting at Sunday=1, and — unlike standard cron — requires you to put `?` in one of day-of-month or day-of-week to make the OR ambiguity explicit. AWS EventBridge's cron is Quartz-derived and has the same day-of-month/day-of-week restriction. Reading someone else's cron expression cold, or writing one for a system you don't touch often, is exactly the kind of thing that's easy to get subtly wrong — which is why Cronwright's visual builder and plain-English preview exist: build it visually, or paste one to see in plain language when it will actually run, across Standard, Quartz, and EventBridge dialects.

The app

How it compares to other tools

Frequently asked questions

What do the five fields in a cron expression mean?

In order: minute (0-59), hour (0-23), day of month (1-31), month (1-12), and day of week (0-6 or 1-7 depending on the system). Each field can be a specific value, a wildcard `*`, a range (`1-5`), a list (`MON,WED,FRI`), or a step (`*/15`).

Why does 0 0 15 * MON run on both the 15th and every Monday, not just Mondays that fall on the 15th?

Standard cron treats day-of-month and day-of-week as an OR when both are restricted, not an AND. If you actually want "the 15th, only if it's a Monday," cron alone can't express that — you'd need an external check or a scheduler dialect (like Quartz) that lets you set one of the two fields to a non-conflicting placeholder.

What's different about Quartz cron compared to standard cron?

Quartz adds a seconds field (making it six or seven fields total, with an optional year), numbers day-of-week 1-7 starting from Sunday, and requires a `?` placeholder in either the day-of-month or day-of-week field to resolve the ambiguity that standard cron leaves implicit. AWS EventBridge's cron syntax is derived from Quartz and shares this rule.

Does */15 * * * * mean 'every 15 minutes from now'?

No — it means every 15 minutes on the clock, aligned to the hour: :00, :15, :30, :45. It doesn't shift based on when the job was scheduled or last ran.