A cron expression is a compact string of space-separated time fields that tells a scheduler exactly when a recurring job should run, for example every 15 minutes, every weekday at 06:30 or on the first day of each month. In scheduling and automation, cron expressions are the de facto standard notation for recurring time-based triggers, used by Unix cron, container orchestrators, CI pipelines, cloud schedulers and workflow platforms.
The format comes from the Unix cron daemon, whose name derives from the Greek word for time. A scheduler evaluates the expression against the clock and starts the job whenever the current time matches every field, which makes cron expressions precise but also easy to misread.
How a cron expression is structured
A standard cron expression has five fields, read from left to right as minute, hour, day of month, month and day of week. A job runs when the current time matches all of the time fields, with one exception described below for the two day fields.
| Position | Field | Allowed values | Example |
|---|---|---|---|
| 1 | Minute | 0-59 | 30 |
| 2 | Hour | 0-23 | 6 |
| 3 | Day of month | 1-31 | 1 |
| 4 | Month | 1-12 or JAN-DEC | * |
| 5 | Day of week | 0-6 or SUN-SAT, 7 also Sunday in many implementations | MON-FRI |
The expression 30 6 * * MON-FRI therefore means 06:30 every Monday to Friday. Hours use the 24-hour clock, and times are interpreted in the scheduler’s configured time zone, which is often UTC on servers and cloud platforms.
A frequently misunderstood rule concerns the two day fields. In classic Unix cron, when both day of month and day of week are restricted, the job runs when either one matches, not both. The expression 0 9 13 * FRI runs on every 13th and on every Friday, not only on Friday the 13th.
Special characters and shortcuts
Cron expressions gain their expressive power from a small set of special characters that describe lists, ranges and steps within a field. Combined, they cover most recurring schedules in a single line.
| Character | Meaning | Example | Result |
|---|---|---|---|
| Asterisk | Every value of the field | * in hour | Every hour |
| Comma | List of values | 0,30 in minute | At :00 and :30 |
| Hyphen | Inclusive range | 9-17 in hour | Every hour from 9 to 17 |
| Slash | Step within a range | */15 in minute | At :00, :15, :30, :45 |
| L | Last day or last weekday | L in day of month | Last day of the month |
| W | Nearest weekday | 15W in day of month | Weekday closest to the 15th |
| Hash | Nth weekday of the month | MON#2 in day of week | Second Monday |
The characters L, W and the hash sign are extensions, supported by schedulers such as Quartz and several cloud services but not by classic Unix cron. Many implementations also accept macros such as @hourly, @daily, @weekly, @monthly and @reboot as readable shortcuts for common schedules.
Dialects across schedulers
There is no single cron standard, and the same string can mean different things in different tools. The main differences concern the number of fields, the presence of seconds and years, and the handling of the day fields.
| Dialect | Fields | Notable differences |
|---|---|---|
| Unix and Linux cron | 5 | Day fields combined with OR, no seconds |
| Quartz scheduler | 6 or 7, with seconds and optional year | Requires ? in one day field, supports L, W, # |
| Kubernetes CronJob | 5 | Unix-style syntax, optional time zone setting |
| Cloud schedulers | 5 or 6 | Vary in year field, extensions and time zone handling |
| CI pipeline schedules | 5 | Often UTC only, runs may be delayed under load |
The difference matters in practice: 0 0 12 * * ? is a valid Quartz expression for noon every day, but it is invalid in Unix cron. In Quartz, day of week usually counts 1 as Sunday, while Unix cron uses 0 as Sunday, a common source of off-by-one-day errors when schedules move between systems.
Cron expressions compared with other scheduling methods
A cron expression describes calendar-based recurrence; it says nothing about retries, dependencies or what happens when a run is missed. Those concerns belong to the task scheduler that interprets the expression.
| Method | Best for | Limitation |
|---|---|---|
| Cron expression | Calendar-aligned recurring jobs | No built-in dependencies or retries |
| Fixed interval | Every N seconds from the last run | Drifts from calendar boundaries |
| Delayed job | Single run after a delay or at a set time | Not recurring by itself |
| Event trigger | Reacting to webhooks or messages | No time guarantee |
| Job dependency | Running after another job completes | Needs an orchestrator |
Fixed intervals and cron schedules are often confused. */7 in the minute field does not mean every seven minutes forever: it means minutes 0, 7, 14 up to 56, after which the cycle restarts at the next hour, leaving a four-minute gap. Steps that do not divide 60 evenly behave this way in every field.
Common pitfalls and good practice
Most cron-related incidents are caused not by syntax errors but by wrong assumptions about time, overlap and missed runs. Experienced teams apply a consistent set of safeguards.
- Daylight saving time: in local time zones, a job at 02:30 may be skipped or run twice when clocks change; schedule critical jobs in UTC or outside the transition hour.
- Overlapping runs: a job that runs longer than its interval starts a second copy unless a concurrency limit or lock prevents it.
- Missed runs: if the scheduler is down at the scheduled time, classic cron does not catch up; a backfill policy must be defined explicitly.
- Thundering herd: many jobs scheduled at minute 0 overload shared systems; spreading start minutes avoids load spikes.
- Silent failures: cron itself does not alert; jobs need monitoring that detects runs that did not happen.
- Unclear intent: a comment next to every expression stating the schedule in words prevents misreading.
Before deploying a new schedule, it is good practice to list the next several run times with a parser for the target dialect and confirm they match the intended calendar, especially for expressions that combine day fields or step values.
In everyday language
A cron expression is a very short way of writing down a repeating appointment for a computer. Instead of saying “every weekday at half past six”, you write five small codes. They stand for minute, hour, day, month and weekday. The computer checks the clock against them every minute.
It works like setting an alarm with repeat options, but far more flexible. The catch is that the shorthand is easy to misread, so a schedule that looks right can quietly run on the wrong days or at the wrong hour.
Seen in the real world
An online retailer exports the previous day’s orders to its accounting system every night. The data team first schedules the export with 0 2 * * * in the server’s local time zone. In spring, the clock jumps from 02:00 to 03:00 and the export silently does not run, leaving accountants without a day of orders.
The team moves the schedule to UTC with 30 1 * * *, adds a lock so that two exports never overlap, and sets an alert that fires if no successful run is recorded by 04:00 UTC. It also documents the schedule in plain words next to the expression. Since the change, exports run once every night regardless of daylight saving, and any missed run is noticed within hours rather than at month-end.