Cron Expression Explainer & Visualizer
Paste any cron expression to get a plain-English explanation and the next 10 scheduled run times. Supports 5-field standard cron, 6-field (with seconds), and shorthand like @daily, @weekly, @monthly.
Reading a Schedule Written in Five Fields
A cron expression is a compact string of five whitespace-separated fields β minute, hour, day-of-month, month, and day-of-week β that defines a recurring schedule, first introduced in Unix Version 7 and still the default scheduling primitive across Linux systems, container orchestrators, and CI/CD platforms today. Each field accepts a wildcard (*, meaning "every value"), a specific number, a range (1-5), a step (*/15), or a comma-separated list (0,15,30,45), and all five can be combined in the same expression β which is exactly what makes cron both compact and easy to misread.
For a DevOps or SRE engineer, a misread cron expression is not a cosmetic bug: it directly determines when a backup runs, when a certificate renewal job fires, or when a database maintenance window begins. This explainer exists because translating 0 2 * * 1 into "runs at 2:00 AM every Monday" reliably, in your head, under time pressure, during a code review, is harder than it looks.
Cron vs Newer Scheduling Options
Cron's five-field format has near-universal support but two structural limits worth knowing: it has no concept of timezone β a plain crontab runs in the server's local time, while Kubernetes CronJobs default to UTC β and it has no built-in retry, alerting, or overlap protection, so a job that crashes silently simply doesn't run again until its next scheduled tick. Newer schedulers layer solutions on top of the same five-field syntax rather than replacing it: AWS EventBridge Scheduler and Quartz both add an optional sixth seconds field and support per-rule timezones, while workflow orchestrators like Airflow or Temporal add retries, dependency graphs, and alerting around a cron-like trigger rather than reinventing the schedule syntax itself.
The practical trade-off: plain cron remains the right choice for a single, independent, idempotent task, such as log rotation or a nightly cleanup script, while anything needing retries, dependency ordering, or cross-timezone correctness benefits from a scheduler built on top of cron syntax rather than raw crontab entries scattered across servers.
Where Cron Expressions Go Wrong
- Assuming day-of-month and day-of-week combine with AND logic: when both fields are restricted, most cron implementations OR them together β
0 0 15 * 1runs on the 15th of every month and every Monday, not only on Mondays that happen to fall on the 15th. - Forgetting which timezone the scheduler actually uses: a plain crontab runs in local server time, but Kubernetes CronJobs default to UTC β an unstated assumption here has caused more than one job to fire at an unexpected hour.
- Stacking every nightly job at exactly midnight: scheduling several unrelated batch jobs all at
0 0 * * *creates a resource contention spike the moment they all hit the same database or API simultaneously. - Treating cron as a retry mechanism: cron has no concept of failure β a job that errors out just sits silently until its next tick, so relying on "it'll just run again later" as a safety net instead of adding real alerting is a common and avoidable gap.
The Midnight Job That Ran Every Minute
A classic incident starts with an engineer intending to schedule a job for midnight and typing * 0 * * * instead of 0 0 * * *, swapping the minute and hour fields. The asterisk in the minute field means "every minute," so instead of running once at midnight, the job fires 60 times between 00:00 and 00:59 every night. If the job is a lightweight health check, this might go unnoticed for weeks; if it's a database backup or a report-generation script, the result is 60x the expected load, duplicate output files, or a downstream system overwhelmed by near-simultaneous triggers.
The postmortem fix is rarely just "be more careful with field order" β teams that get burned by this typically add a pre-deployment check that renders every new cron expression in plain English, exactly what this tool does, before it's merged, catching field-order mistakes the moment they're written rather than after they've run in production for a week.
Checking Your Work at the Command Line
Every field this tool parses maps directly onto the crontab format read by crontab -e, and most Linux distributions ship a way to inspect an expression without waiting for it to fire: crontab -l lists installed jobs for review, and a quick man 5 crontab confirms field ranges when in doubt. For systemd-based systems, the equivalent construct is a timer unit's OnCalendar= directive, which uses a different but related calendar-event syntax β systemd-analyze calendar "Mon *-*-* 02:00:00" prints the next several trigger times directly from the command line, serving the same verification purpose as this page's next-run list but for systemd timers instead of crontab entries.
Frequently Asked Questions
What is a cron expression?
A cron expression is a string of five whitespace-separated fields that defines a recurring schedule: minute (0β59), hour (0β23), day-of-month (1β31), month (1β12), and day-of-week (0β7, where both 0 and 7 represent Sunday). For example, 0 9 * * 1-5 means "at 9:00 AM every weekday". Cron was originally introduced in Unix Version 7 and remains the standard scheduling primitive across Linux systems, container orchestrators, CI/CD platforms, and cloud-native schedulers alike.
What does the asterisk (*) mean in cron?
The asterisk means "every possible value" for that field. So * * * * * means every minute of every hour of every day. You can combine the asterisk with a step value: */5 in the minute field means "every 5 minutes", while */2 in the hour field means "every 2 hours". You can also use ranges like 1-5 to match a consecutive span, or comma-separated lists like 0,15,30,45 to match specific values β all of which can be mixed in a single expression.
How does cron syntax differ between Linux cron and Kubernetes CronJobs?
Standard Linux cron uses five fields (minute, hour, day-of-month, month, day-of-week) and runs in the local timezone of the server. Kubernetes CronJob spec uses the same five-field format but schedules are evaluated in UTC by default, and the job may start up to a minute late due to the controller's reconciliation interval β this is important to account for when scheduling time-sensitive operations. Some systems such as AWS EventBridge Scheduler, Spring @Scheduled, and Quartz add a sixth seconds field at the beginning of the expression, making those expressions incompatible with standard cron parsers and requiring careful documentation when sharing expressions across teams.