Cron expressions explained (for people who forget them every time)
The five fields, the special characters, and the schedules everyone actually uses. A field guide for anyone who Googles 'cron every 5 minutes' more than once a month.
The five fields
Standard Unix cron is five space-separated fields, in this order:
* * * * *
| | | | |
| | | | +-- day of week (0-6, Sunday = 0)
| | | +---- month (1-12)
| | +------ day of month (1-31)
| +-------- hour (0-23)
+---------- minute (0-59)
Each field accepts:
- A single number -
5means "5" (5 minutes past the hour if in the minute field). - A range -
1-5means "1, 2, 3, 4, 5". - A list -
1,3,5means "1 or 3 or 5". - A step -
*/15means "every 15" (from 0).10-30/5means "every 5 within 10-30". - A wildcard -
*means "every value".
That's the entire grammar. Everything else is convenience.
The schedules everyone actually uses
Bookmark this table and you'll never Google "cron every 5 minutes" again:
* * * * *- every minute.*/5 * * * *- every 5 minutes.0 * * * *- every hour, on the hour.0 */3 * * *- every 3 hours.0 0 * * *- midnight every day.0 9 * * 1-5- 9 AM every weekday.0 9 * * 1- 9 AM every Monday.30 3 * * 0- 3:30 AM every Sunday.0 0 1 * *- midnight on the 1st of every month.0 0 1 1 *- midnight on January 1st (annually).
The special strings
Most cron implementations accept these shortcuts:
@yearly(or@annually) โ0 0 1 1 *@monthlyโ0 0 1 * *@weeklyโ0 0 * * 0@daily(or@midnight) โ0 0 * * *@hourlyโ0 * * * *@reboot- run once at boot (event-triggered, not a schedule).
Portable across most Linux distros. Not supported by every cron implementation (BusyBox cron on Alpine, for instance, only supports @reboot).
The gotchas that cost real time
Timezones. Your server's crontab runs in the server's timezone. If your server is in UTC and you want a job at 9 AM Eastern, use 0 14 * * * (or 0 13 * * * in daylight saving time - which is why "9 AM Eastern" schedules break twice a year). Better: set CRON_TZ=America/New_York at the top of the crontab if your cron supports it.
Day-of-month and day-of-week are OR'd. 0 0 1 * 1 runs at midnight on either the 1st of any month OR every Monday - not "midnight on the 1st only if it's a Monday". If you want an AND, use two separate cron entries or check the day inside your script.
Environment variables. Cron runs jobs with a stripped-down environment. PATH is often just /usr/bin:/bin. Your script that works interactively may fail from cron because node, python, or aws aren't on the path. Fix: use absolute paths, or set PATH at the top of the crontab.
Output silently emailed (or lost). By default cron mails stdout/stderr to the local user. On modern servers with no mail daemon, the output vanishes. Redirect: 0 * * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1.
Overlapping runs. Nothing prevents a slow job from starting again while the previous run is still going. Wrap with flock: 0 * * * * flock -n /tmp/backup.lock /usr/local/bin/backup.sh.
Quartz cron: don't confuse it with Unix cron
Java's Quartz scheduler, Spring's @Scheduled, and AWS EventBridge use a 6- or 7-field cron with seconds and years. Quartz also supports ?, L (last day of the month), W (nearest weekday), and # (nth day of the month). None of these work in standard Unix cron.
If you're setting up a Kubernetes CronJob, Linux crontab, or GitHub Actions schedule: 5 fields, no seconds. If you're setting up Spring, Quartz, or AWS EventBridge: 6-7 fields with seconds.
Cron Generator targets standard 5-field Unix cron, since that's what 90% of scheduling systems use.
The verification workflow
Building a cron expression is a two-step debug cycle:
- Write the expression - pick minute, hour, day, etc.
- Verify the next N run times match what you meant.
Step 2 is the one everyone skips. It's also the one that catches "wait, I wrote day-of-week when I meant day-of-month" before it hits production.
Cron Generator shows a plain-English translation and the next 5 run times as you build the expression. Paste an existing crontab entry to explain it - often faster than re-deriving what past-you meant.
Related tools:
- Regex Tester - when your cron job is grep-ing log files and you need to check the pattern.
- JSON Formatter - when the job's output is JSON and you need to eyeball it.
Tools mentioned in this post
Related reading
The Unix timestamp cheat sheet every developer wishes they had bookmarked
Seconds vs milliseconds vs microseconds, ISO 8601 vs RFC 3339, timezones, DST, leap seconds - the reference for every 'wait, is this in ms?' moment.
The regex cheat sheet every JavaScript developer actually needs
Forget lookbehind edge cases. Here are the 15 patterns you'll use in real code - validation, extraction, replacement - with the JavaScript-specific gotchas.
Why your JSON won't parse (and how to fix it in 30 seconds)
Trailing commas, unquoted keys, single quotes, comments - the five errors that break 90% of hand-written JSON, and how to catch them without a build step.
The best free 2027 calendar online with reminders (no signup, no account)
A full-year 2027 calendar in your browser - add events, set reminders, get browser notifications when the time comes. Everything stored locally, no login, no cloud, no ads. Here's when to use it vs Google Calendar, Outlook or Apple Calendar.
Shan builds 712 Tools. He holds a Master's degree in Mechanical Engineering and now works as a Software Engineer, shipping browser-based developer utilities out of Ontario, Canada. Learn more ยท 712studiogames@gmail.com