Cron Expression Guide: Syntax, Fields & Platform Differences
Cron is a time-based job scheduler built into Unix-like operating systems. A cron expression is a compact string that defines when a job should run — once you understand the five fields and the handful of special characters, you can express almost any schedule imaginable, from "every minute" to "at 8:45 AM on the first Monday of every quarter." This is the reference page for the syntax itself; if you have a specific expression already and just want it explained, the free Cron Expression Explainer will do that instantly.
The Five Fields
Every standard cron expression has exactly five fields separated by spaces:
┌─ minute (0 – 59) │ ┌─ hour (0 – 23) │ │ ┌─ day/month (1 – 31) │ │ │ ┌─ month (1 – 12) │ │ │ │ ┌─ day/week (0 – 6, 0 = Sunday) │ │ │ │ │ * * * * *
Special Characters
*— matches every possible value for that field.,— list separator.1,3,5means the 1st, 3rd, and 5th.-— range.1-5means 1 through 5./— step.*/10means every 10 units, starting from 0.
10 Practical Examples
* * * * *— every minute0 * * * *— every hour on the hour0 0 * * *— every day at midnight0 9 * * 1-5— weekdays at 9:00 AM*/15 * * * *— every 15 minutes0 0 1 * *— first day of every month at midnight30 18 * * 5— every Friday at 6:30 PM0 8,12,18 * * *— at 8 AM, noon, and 6 PM daily0 0 * * 0— every Sunday at midnight0 2 * * 1— every Monday at 2:00 AM (good for weekly backups)
Need "every 5 minutes" specifically, with more variations? See cron every 5 minutes: expression and examples.
Real-World Application Patterns
Beyond the syntax, here's what these expressions actually get used for in production:
- Database backups —
0 2 * * *, nightly during low-traffic hours, before the day's data volume makes the backup window too long. - Log rotation and cleanup —
0 0 * * 0, weekly, deleting or archiving logs older than a retention window so disk usage doesn't grow unbounded. - Cache warming —
*/15 * * * *, refreshing a computed cache slightly before it would otherwise expire, so users never hit a cold cache. - Scheduled reports —
0 8 1 * *, generating and emailing a monthly summary on the 1st at 8 AM, timed to land before the workday starts. - Health checks and monitoring pings —
*/5 * * * *, checking a service is still responding and alerting if a run is missed (see the monitoring guide linked below for how to detect a silent failure — a cron job that stops running without erroring). - Token or session cleanup —
0 3 * * *, nightly removal of expired auth tokens or stale sessions from the database.
Common Mistakes to Avoid
- Confusing day-of-week numbering — Sunday is
0on most systems, but7is also accepted on some. - Forgetting that month and day-of-month are 1-indexed while hour and minute are 0-indexed.
- Using
0/5instead of*/5— both work but*/5is clearer. - Writing six fields for a standard crontab — the extra field (seconds or year) is only understood by specific schedulers like Quartz or node-cron, not plain Unix cron.
- Specifying both day-of-month and day-of-week and assuming it means "and" — on standard cron it means "or": the job runs if either field matches.
Platform Comparison
Cron syntax is mostly standard, but every platform that implements it has quirks:
| Platform | Fields | Timezone | Notable quirk |
|---|---|---|---|
| Linux / Unix crontab | 5 | System timezone | Minimal environment — no login shell PATH by default |
| GitHub Actions | 5 | UTC only | 5-minute minimum interval; can be delayed further under load |
| AWS EventBridge | 6 (adds year) | UTC only | Day-of-month and day-of-week can't both be a value — one must be ? |
| GCP Cloud Scheduler | 5 | Configurable per job | Only unix cron using standard 5-field syntax is accepted |
| node-cron (Node.js) | 5 or 6 | Process timezone by default, configurable | Optional leading seconds field for sub-minute schedules |
| Quartz (Java) | 6 or 7 | Configurable per trigger | Seconds field is required, not optional — a 5-field unix expression is invalid here |
For the Quartz/Java seconds-field trap specifically, see Cron vs Quartz in Java.
Troubleshooting: My Cron Job Isn't Running
The short version — check these in order:
- Is the cron daemon actually running? (
systemctl status cronon most Linux distros) - Does the crontab use an absolute path to the script, not a relative one?
- Does the script depend on environment variables that exist in your login shell but not in cron's minimal environment?
- Does the file running the job have execute permission?
For the full checklist with the exact commands to run for each check, see Cron Job Not Running? 5 Fixes That Actually Work.
Describe a schedule in plain English and get the expression with the Cron Generator, or paste an expression you already have to see what it means and its next run times with the Cron Expression Explainer. Both are free, with nothing stored.
Frequently Asked Questions
Cron is the background daemon (process) that runs on a schedule. Crontab ("cron table") is both the file format used to define schedules and the command (crontab -e) used to edit that file. In everyday conversation "cron" and "crontab" are often used interchangeably, but strictly: cron runs the jobs, crontab is how you tell it what to run and when.
No — standard cron's smallest unit is one minute; there is no seconds field. To run something every 10 or 30 seconds, either call your script twice from cron with a sleep 30 in between, use a scheduler that supports sub-minute intervals (node-cron and Quartz both support an optional seconds field), or use a long-running process with its own internal timer instead of cron.
The most common causes: the cron daemon isn't running, the script path in the crontab isn't absolute, the script relies on environment variables that don't exist in cron's minimal environment, or a permissions issue. See the full troubleshooting guide below for the complete checklist with commands.
By default, cron uses the system timezone of the machine it runs on — not your local timezone, and not UTC unless the server happens to be set to UTC. This is one of the most common sources of 'why did my job run at the wrong time' bugs. See the dedicated timezone guide below for how to check and set this correctly.