Cron expressions are powerful and concise — but they're also easy to get wrong and surprisingly hard to read at a glance. Our free cron expression tester tells you exactly what any cron schedule means in plain English, and shows you the next several run times so you can verify the schedule before deploying it.
→ Test a cron expression now (free tool)
Paste any standard 5-field cron expression and get an instant human-readable interpretation: "Every Monday at 3:00 AM." No guessing, no counting fields.
A cron expression looks deceptively simple. Five space-separated fields, each controlling a unit of time. But the combination of special characters — asterisks, slashes, commas, hyphens, and sometimes question marks — makes even experienced developers pause when reading an expression they didn't write themselves.
Is that "every Monday at 3:00 AM" or "the 1st of every month at 3:00 AM"? (It's Monday — field 5 is day-of-week, not day-of-month.) Now try this one:
*/15 9-17 * * 1-5
Every 15 minutes, between 9am and 5pm, Monday through Friday. Reasonable to figure out — but not instantly obvious. The moment you add ranges, step values, and multiple comma-separated values, the cognitive overhead compounds fast.
A cron expression tester removes that overhead entirely. Paste it in, read the English, confirm the next 5 run times, done.
A standard cron expression has exactly five fields, separated by spaces:
| Field | Position | Range | Example |
|---|---|---|---|
| Minute | 1st | 0–59 | 30 = at minute 30 |
| Hour | 2nd | 0–23 | 3 = 3 AM |
| Day of month | 3rd | 1–31 | 1 = 1st of month |
| Month | 4th | 1–12 | */3 = every 3 months |
| Day of week | 5th | 0–7 (0 and 7 = Sunday) | 1-5 = Mon–Fri |
The field order is always the same: minute, hour, day-of-month, month, day-of-week. A useful mnemonic: M H D M D — minute, hour, day, month, day-of-week.
* — every value in this field ("every minute", "every hour", etc.)*/n — every nth value (e.g. */5 in the minute field = every 5 minutes)a-b — a range from a to b inclusive (e.g. 9-17 in the hour field = 9am through 5pm)a,b,c — a list of specific values (e.g. 1,15 in day-of-month = 1st and 15th)0-5 means Sunday through Friday, not Monday through Friday. To get Monday–Friday, use 1-5. This trips up many developers who expect 0-indexed Monday.
Here are the most frequently used patterns and what they mean:
| Expression | Meaning |
|---|---|
* * * * * |
Every minute |
0 * * * * |
Every hour (at :00) |
0 0 * * * |
Every day at midnight |
0 3 * * * |
Every day at 3:00 AM |
0 0 * * 0 |
Every Sunday at midnight |
0 9 * * 1-5 |
Weekdays at 9:00 AM |
0 0 1 * * |
First of every month at midnight |
*/15 * * * * |
Every 15 minutes |
0 */6 * * * |
Every 6 hours (at :00) |
30 9 1,15 * * |
9:30 AM on the 1st and 15th of each month |
Unsure whether your expression matches what you intended? Paste it into the cron expression tester — it shows the next 10 scheduled run times, so you can immediately verify the pattern is correct.
Standard 5-field cron expressions work in Linux crontab, most Unix systems, and most job schedulers. But some platforms have their own variations — and knowing the difference can save you a frustrating debugging session.
GitHub Actions uses the same 5-field format with a UTC timezone. Note: GitHub documentation warns that scheduled workflows may run up to 15 minutes late during periods of high load. */5 in the minute field is the minimum interval GitHub allows.
on:
schedule:
- cron: '0 3 * * 1' # Monday at 3:00 AM UTC
AWS uses a 6-field cron format with an additional year field at the end, and uses ? as a wildcard for either day-of-month or day-of-week (not both can be specified). Their expressions look like:
cron(0 3 ? * MON *) # Monday at 3:00 AM UTC, every year
AWS also supports named days (MON, TUE, etc.) and months (JAN, FEB, etc.) in addition to numeric values.
Kubernetes uses standard 5-field cron syntax. The schedule field follows Unix cron conventions exactly. Timezones can be specified with a timeZone field in the spec (since Kubernetes 1.25).
Heroku Scheduler uses a simplified interface — every 10 minutes, every hour, or daily at a specific UTC time. It does not support arbitrary cron expressions.
The best practice before deploying any cron job is to validate the expression in three ways:
Our cron expression parser handles all three: it gives you the plain-English translation, the next 10 run times, and lets you select a timezone for the preview. Paste in your expression, verify the output, then deploy with confidence.
0 0 * * * runs at midnight server time — which may not be midnight in your timezone or your users' timezone. If you're running a report "for yesterday's data," running at midnight UTC means it runs mid-afternoon Pacific — potentially before the business day ends. Always be explicit about which midnight you mean.
Validating the expression before deploy is step one. But once a cron job is running, a whole different class of problems can emerge: the job starts but fails partway through, auto-renewal processes stop running, or a scheduler itself goes down. Syntax validation doesn't catch runtime failures.
The standard pattern for detecting missed cron runs is a dead man's switch: your job pings a monitoring service on successful completion, and the service alerts you if the ping doesn't arrive within the expected window. One curl command at the end of your job is all it takes.
CronWatch monitors your scheduled jobs across crontab, GitHub Actions, AWS EventBridge, Kubernetes CronJob, and Heroku Scheduler. Get alerted in Slack or email within minutes of a missed window or job failure.
Join the CronWatch waitlist → Test a cron expression (free)