Why Cron Still Matters (And Why I Write It Wrong Every Time)
I've been a developer for over a decade, and I still can't write a cron expression from memory. Not reliably. Is day of week 0-6 or 1-7? Does month come before or after day? What's that slash thing again?
And yet, cron is everywhere. Database backups. Log rotation. Email digests. Report generation. Every production system I've ever worked on has cron jobs running somewhere. It's one of those Unix technologies that refuses to die because nothing better has replaced it.
What Is Cron, Exactly?
Cron is a time-based job scheduler in Unix-like operating systems. It runs tasks (called "cron jobs") at specified intervals. The name comes from "chronos," the Greek word for time.
A cron expression defines the schedule. It's a string of five fields:
ββββββββββββββ minute (0-59)
β ββββββββββββββ hour (0-23)
β β ββββββββββββββ day of month (1-31)
β β β ββββββββββββββ month (1-12)
β β β β ββββββββββββββ day of week (0-6, Sunday=0)
β β β β β
* * * * *
Each field can be a specific value, a range, a list, or a pattern. The asterisk means "every."
π Developer Story #1: The Backup That Never Ran
Background: A startup had set up daily database backups. The cron job ran 0 0 * * *βmidnight every day. For months, everything seemed fine.
The Problem: One day, they needed to restore. The backups were empty files. The backup script worked perfectly when run manually but silently failed from cron.
The Cause: The script relied on environment variables that weren't set in the cron environment. PATH was different. Database credentials weren't loaded. Cron runs with a minimal environment.
Lesson: Always test cron jobs in the actual cron environment. Use full paths. Source your environment explicitly. And most importantlyβverify your backups actually contain data.
Common Cron Patterns
Here are the expressions I look up most often:
| Expression | Description |
|---|---|
* * * * * | Every minute |
*/5 * * * * | Every 5 minutes |
0 * * * * | Every hour (at minute 0) |
0 0 * * * | Daily at midnight |
0 9 * * 1-5 | Weekdays at 9 AM |
0 0 * * 0 | Weekly on Sunday |
0 0 1 * * | Monthly on the 1st |
0 0 1 1 * | Yearly on January 1st |
The Tricky Bits Nobody Explains
Day of Week vs Day of Month
Here's where it gets confusing. If you set both day of month AND day of week, they're OR'd together, not AND'd. 0 0 15 * 1 means "midnight on the 15th OR any Monday"βnot "the 15th if it's a Monday."
Timezone Matters
Cron uses the system timezone, not UTC. If your server is in UTC but you want jobs at 9 AM New York time, you need to calculate the offsetβand remember Daylight Saving Time changes it twice a year.
The Slash Syntax
*/5 means "every 5," starting from 0. But 3/5 means "every 5, starting from 3"βso minute 3, 8, 13, 18... This trips people up.
π Developer Story #2: The Duplicate Email Disaster
Background: An e-commerce site sent order summary emails to customers every morning at 8 AM. The cron: 0 8 * * *.
The Problem: After a server migration, customers started receiving 2-3 identical emails. Support tickets exploded.
The Cause: The migration copied the crontab, but the new server was in a different timezone. The job ran at 8 AM in both the old timezone (still running) and the new timezone. Plus, they had a duplicate crontab entry from testing.
Lesson: Document your cron jobs' timezone intentions. After migrations, verify crontabs on both old and new servers. Use a centralized scheduler for critical jobs.
Cron Variations Across Platforms
Standard cron has 5 fields, but different platforms extend it:
Extended Cron (6 fields)
Some systems add a seconds field at the beginning:
ββββββββββββββ second (0-59)
β ββββββββββββββ minute (0-59)
β β ββββββββββββββ hour (0-23)
β β β ββββββββββββββ day of month (1-31)
β β β β ββββββββββββββ month (1-12)
β β β β β ββββββββββββββ day of week (0-6)
β β β β β β
* * * * * *
Spring Scheduler and Quartz (Java) use this format. AWS CloudWatch Events uses a slightly different syntax.
Kubernetes CronJobs
Kubernetes uses standard 5-field cron but runs in UTC by default. You can use timezone-aware cron starting in Kubernetes 1.27.
AWS CloudWatch / EventBridge
AWS uses "rate expressions" (rate(5 minutes)) and "cron expressions" with an optional year field and slight syntax differences.
π‘ Pro Tip:
When debugging cron, add logging. Redirect stdout and stderr to a file: * * * * * /path/script.sh >> /var/log/myjob.log 2>&1. You'll thank yourself later.
π Developer Story #3: The "Every 5 Minutes" That Wasn't
Background: A data sync job needed to run every 5 minutes. Developer wrote 5 * * * *.
The Problem: The sync was running once an hour, not every 5 minutes. Data was always stale.
The Cause: 5 * * * * means "at minute 5 of every hour"βonce an hour at :05. They needed */5 * * * * for "every 5 minutes."
Lesson: 5 is a specific value. */5 is an interval. This tool's "Next Run Times" feature would have caught this instantlyβalways verify the schedule before deploying.
Best Practices for Cron Jobs
1. Use Absolute Paths
Cron's PATH is minimal. Use /usr/bin/python3, not python3. Use full paths to your scripts.
2. Add Locking
If a job takes longer than the interval, you might get overlapping runs. Use flock or implement your own locking to prevent this.
3. Handle Failures Gracefully
Cron will send email on errors (if configured), but you might want Slack/PagerDuty alerts. ExitOnError. Log everything.
4. Document Your Jobs
Comments in crontab are free: # Nightly backup - runs at 2 AM to avoid peak hours. Future you will appreciate it.
5. Consider Alternatives for Complex Scheduling
If you need retries, dependencies between jobs, or complex DAGs, consider tools like Airflow, Temporal, or Celery Beat.
How This Tool Works
This generator lets you build cron expressions visually. Select options for each field, and the expression updates in real-time. You can also:
- Use presets for common schedules
- Parse existing expressions to understand them
- See next run times to verify the schedule
- Copy the expression directly to your crontab
Everything runs in your browserβno data is sent anywhere.
Final Thoughts
Cron is 50 years old and still going strong. It's not always the prettiest solution, but it works, it's reliable, and it's everywhere. Every developer should understand how to write and debug cron expressionsβeven if we still need to look up the syntax every single time.
Bookmark this tool. You'll use it more than you think.




