Complete Guide to Cron Expressions: Schedule Tasks Reliably
Master cron expression syntax and patterns for Unix/Linux systems, cloud platforms, and application job schedulers. Learn how to schedule tasks reliably with real-world examples.
What is Cron?
Cron is a time-based job scheduler for Unix and Unix-like systems (Linux, macOS, BSD). It allows you to schedule tasks to run automatically at specific times and intervals.
Cron has evolved beyond just Unix systems. Modern cloud platforms (AWS, Google Cloud, Azure), containerized systems (Kubernetes), CI/CD platforms (GitHub Actions, GitLab), and application frameworks (Node.js, Python, Java) all support cron expressions as a standard scheduling syntax.
Why Use Cron?
- Automation — Run tasks automatically without manual intervention
- Scalability — Schedule thousands of jobs efficiently
- Reliability — Standard, battle-tested syntax used everywhere
- Cost-effective — No need to keep processes running 24/7
Common Cron Use Cases
- Backup databases at 2 AM daily
- Send reports every Monday morning
- Clean up old logs every Sunday
- Run tests every 6 hours
- Process batch jobs at 1 AM
- Send reminder emails every weekday at 9 AM
The Five Fields
A cron expression consists of exactly 5 fields, separated by spaces:
minute hour day-of-month month day-of-week 0 0 * * *
Field 1: Minute (0-59)
Which minute of the hour. 0 = top of the hour, 30 = half past.Example: 30 * * * * runs at 30 minutes past every hour.
Field 2: Hour (0-23)
Which hour in 24-hour format. 0 = midnight, 12 = noon, 23 = 11 PM.Example: 0 14 * * * runs at 2:00 PM.
Field 3: Day of Month (1-31)
Which day of the month. 1 = first, 15 = 15th, * = every day.Example: 0 0 15 * * runs on the 15th at midnight.
Field 4: Month (1-12)
Which month. 1 = January, 12 = December, * = every month.Example: 0 0 1 1 * runs January 1st at midnight (New Year).
Field 5: Day of Week (0-7)
Which day of the week. 0 and 7 = Sunday, 1 = Monday, 5 = Friday, * = every day.Example: 0 9 ? * 1-5 runs at 9 AM on weekdays.
Important: * vs ?
Use * to mean "any value" — matches everything. Use ? to mean "don't care" — only for day-of-month or day-of-week, never both.
CORRECT: 0 0 15 * ? (15th at midnight, any day of week) CORRECT: 0 0 ? * 1 (Mondays at midnight, any day of month) WRONG: 0 0 15 * 1 (ambiguous — conflicts)
Special Characters
* (Asterisk): Any Value
Matches any value in that field. * * * * * runs every minute, every hour, every day, every month, every day of the week (constantly!).
? (Question Mark): Don't Care
Used only in day-of-month or day-of-week. Means "I don't care about this field." Use when you specify the other one to avoid conflicts.
- (Dash): Range
Specifies a range. 9-17 means 9 through 17 (inclusive). 1-5 in day-of-week means Monday through Friday.
Examples: 0 9-17 * * * (run every hour from 9 AM to 5 PM) * * 1-7 * * (run every minute from 1st to 7th of month)
, (Comma): List
Specifies specific values. 0,30 = at 0 and 30 minutes. 1,3,5 = Monday, Wednesday, Friday.
Examples: 0 9,14 * * * (at 9 AM and 2 PM) 0 0 * * 1,3,5 (midnight on Monday, Wednesday, Friday)
/ (Slash): Step Values
Repeats at intervals. */5 = every 5. 0-23/2 = every 2nd hour from 0 to 23.
Examples: */5 * * * * (every 5 minutes) 0 */6 * * * (every 6 hours) 0 0 */3 * * (every 3 days) 0 9 * * */2 (9 AM every other day)
Common Patterns
Daily Schedules
0 0 * * *— Daily at midnight0 9 * * *— Daily at 9 AM30 14 * * *— Daily at 2:30 PM0 0 * * 1-5— Weekdays at midnight
Hourly & Minute Schedules
0 * * * *— Every hour, top of the hour*/15 * * * *— Every 15 minutes*/5 * * * *— Every 5 minutes0 0,6,12,18 * * *— Every 6 hours
Weekly & Monthly
0 0 * * 0— Weekly on Sunday at midnight0 0 1 * *— First day of each month0 0 1 1 *— January 1st (New Year)0 0 31 12 *— December 31st (New Year's Eve)
Real-World Examples
Database Backup at 2 AM Daily
0 2 * * *
Runs every day at 2:00 AM. Good time for backups when there's minimal activity.
Send Weekly Report Every Monday at 8 AM
0 8 ? * 1
Runs at 8:00 AM on Mondays. The ? for day-of-month means "any day of the month—I only care about Monday."
Process Batch Job Every 4 Hours
0 0,4,8,12,16,20 * * *
Or using step values:
0 */4 * * *
Runs at midnight, 4 AM, 8 AM, noon, 4 PM, and 8 PM.
Send Reminders Weekdays at 9 AM and 2 PM
0 9,14 ? * 1-5
9:00 AM and 2:00 PM on Monday through Friday. The ? ignores the day of month.
Clean Up Old Logs Every Sunday at 3 AM
0 3 ? * 0
3:00 AM on Sundays. Good for intensive maintenance during low-traffic periods.
Run Health Check Every 10 Minutes
*/10 * * * *
Runs at :00, :10, :20, :30, :40, :50 every hour.
Monthly Report on Last Day at Noon
0 12 L * *
Note: Some systems support L for "last day," but standard cron doesn't. Instead, run on the 28th (covers all months): 0 12 28 * *.
Cron in Cloud Platforms
AWS Lambda / EventBridge
AWS uses cron(minute hour day month? dayOfWeek? year). Note the optional month and year fields.
cron(0 14 * * ? *) # Daily at 2 PM UTC
Google Cloud Scheduler
Standard 5-field cron syntax.
0 14 * * * # Daily at 2 PM
GitHub Actions
Uses standard cron for scheduled workflows.
on: schedule: - cron: '0 9 * * 1-5' # Weekdays at 9 AM UTC
Kubernetes CronJobs
Standard cron with 6 fields (adds seconds at the beginning).
0 0 14 * * * # Daily at 2 PM, 0 seconds
Important: Timezones
Cloud platforms typically use UTC. If you need a specific timezone, check platform docs. AWS Lambda is UTC. Some platforms let you specify timezone explicitly.
Best Practices
1. Verify Before Deploying
Always test your cron expression in a tool like Cron Expression Generator Pro to see the next execution times. Catch mistakes before they cause problems.
2. Avoid Midnight If Possible
All batch jobs running at midnight (0 0) can overload your system. Spread them out: midnight, 1 AM, 2 AM, etc. Or use off-peak hours like 2-4 AM.
3. Account for Timezones
Cloud platforms typically use UTC. If you need a specific timezone, either convert or configure the platform's timezone setting. "9 AM EST" is different from "9 AM UTC".
4. Test with Low Frequency First
When creating a new job, test with something like 0 * * * * (hourly) before moving to longer intervals. Easier to verify hourly runs than daily runs.
5. Monitor Executions
Log when your cron job runs and whether it succeeded. If it doesn't run, check system logs. If it runs at the wrong time, verify your cron expression and system timezone.
6. Use ? for Clarity
If you only care about day-of-week, use ? for day-of-month. It makes your intent clear: "Mondays, I don't care which day of the month."
7. Avoid Every Minute in Production
* * * * * runs 1,440 times per day. This is extreme and often a bug. If you truly need that frequency, consider a background worker or daemon instead.
Debugging Cron Issues
Job Isn't Running at All
- Check expression syntax — Paste into Cron Generator to verify
- Check cron daemon — Is it running? Try
sudo service cron status - Check permissions — Does the cron user have permission to run the job?
- Check logs — Unix:
/var/log/syslog,/var/log/cron. Cloud: check platform dashboard.
Job Runs at Wrong Time
- Verify expression — Use the
?for day-of-month if specifying day-of-week - Check timezone — System timezone may differ from platform timezone. Use explicit timezone if supported.
- Test hourly first — If unsure, use
0 * * * *to verify basic timing
Job Runs Too Frequently
- Check for * * * * * — Most common mistake. This runs every minute!
- Verify step values —
*/1= every 1 (same as *)
Conclusion
Cron expressions are a powerful, standard way to schedule tasks reliably across Unix, cloud platforms, and modern applications. With the five-field syntax and special characters, you can express almost any recurring schedule.
Always test your expressions with Cron Expression Generator Pro before deploying to production. A few minutes of verification saves hours of debugging and prevents jobs from silently failing.