How to Write Reliable Cron Expressions
How to Write Reliable Cron Expressions
Cron expressions schedule recurring tasks in Unix systems, CI/CD pipelines, cloud functions, and job schedulers. A wrong expression can fire a job every minute instead of every month. This guide covers the syntax, common patterns, and pitfalls.
The Five-Field Format
Standard cron uses five fields separated by spaces:
┌───────── minute (0-59)
│ ┌─────── hour (0-23)
│ │ ┌───── day of month (1-31)
│ │ │ ┌─── month (1-12)
│ │ │ │ ┌─ day of week (0-7, where 0 and 7 are Sunday)
│ │ │ │ │
* * * * *
The asterisk * means "every." A number means "at exactly this value."
Common Patterns
Every day at midnight
0 0 * * *
Every hour at minute 0
0 * * * *
Every Monday at 9:00 AM
0 9 * * 1
Every 15 minutes
*/15 * * * *
First day of every month at 6:00 AM
0 6 1 * *
Weekdays at 8:30 AM
30 8 * * 1-5
Every 6 hours
0 */6 * * *
Twice daily at 9 AM and 5 PM
0 9,17 * * *
Special Characters
Comma (,): List of values.1,15 in the day field means the 1st and 15th.
Hyphen (-): Range. 1-5 in the day-of-week field means Monday through Friday.
Slash (/): Step. */10 in the minute field means every 10 minutes. 0/10 is equivalent.
**Asterisk (*)**: Every value in the field.
The Day-of-Month vs Day-of-Week Trap
When both day-of-month and day-of-week are set (not *), traditional cron treats them as OR, not AND. This surprises most people.
Intended: 1st of month IF it is a Monday
Actual: Every 1st of month AND every Monday
0 9 1 * 1
To achieve AND logic, use a wrapper script that checks the day.
Timezone Awareness
Cron jobs run in the system's local timezone by default. This causes problems:
Best practice: Set cron timezone to UTC explicitly.
In crontab (some systems)
CRON_TZ=UTC
0 14 * * * /path/to/script.sh
In GitHub Actions
on:
schedule:
- cron: '0 14 * * *' # Always UTC
Six-Field and Seven-Field Extensions
Some systems add a seconds field at the beginning or a year field at the end:
AWS EventBridge / Quartz (6 fields: seconds included)
0 0 9 * * 1-5 # Weekdays at 9:00:00 AM
Spring (6 fields)
0 */30 * * * * # Every 30 minutes at second 0
Always check your platform's documentation for the expected format.
Testing Cron Expressions
Never deploy a cron expression without testing. Use a cron parser tool to verify:
Online tools like crontab.guru or a cron parser in your dev toolkit can validate expressions instantly.
Common Mistakes
**Forgetting that * means every**: * * * * * runs every single minute. Most scheduled tasks should not run more than once per hour.
Conclusion
Cron expressions are compact but powerful. Always validate before deploying, use UTC for consistency, and be explicit about what you intend. A well-written cron expression runs silently for years — a bad one creates incidents at 3 AM.