What is a Cron Job?
How cron works, how to read and write cron expressions, and common scheduling patterns.
What is a cron job?
A cron job is a scheduled task that runs automatically at a specified time or interval on Unix-based systems. The name comes from Chronos (the Greek god of time) and the daemon that runs the jobs is called cron.
Cron jobs are used for: database backups, sending scheduled emails, generating reports, cleaning up old files, refreshing caches, running health checks, and any task that needs to happen on a schedule without manual intervention.
Cron expression syntax
A cron expression has five fields separated by spaces:
┌─────────── minute (0–59) │ ┌───────── hour (0–23) │ │ ┌─────── day of month (1–31) │ │ │ ┌───── month (1–12) │ │ │ │ ┌─── day of week (0–6, Sunday=0) │ │ │ │ │ * * * * *
Special characters: * (any value) · , (list) · - (range) · / (step)
Common cron expressions
| Expression | Meaning |
|---|---|
| * * * * * | Every minute |
| 0 * * * * | Every hour (at minute 0) |
| 0 0 * * * | Every day at midnight |
| 0 9 * * 1-5 | Weekdays at 9:00 AM |
| 0 0 * * 0 | Every Sunday at midnight |
| 0 0 1 * * | First day of every month at midnight |
| */15 * * * * | Every 15 minutes |
| 0 9,17 * * * | At 9 AM and 5 PM every day |
| 0 0 1 1 * | January 1st at midnight (yearly) |
| 30 2 * * 6 | Every Saturday at 2:30 AM |
Special shortcuts
Many cron implementations support aliases:
@yearly → 0 0 1 1 * (once a year) @monthly → 0 0 1 * * (once a month) @weekly → 0 0 * * 0 (once a week, Sunday) @daily → 0 0 * * * (once a day, midnight) @hourly → 0 * * * * (once an hour) @reboot → run once on startup
Two problems every cron job eventually hits
The thundering herd
Scheduling work at a round time — 0 * * * * — means every instance fires simultaneously. On a single server this is fine. On a fleet of workers, it means dozens of simultaneous database queries at the top of every hour. The fix is jitter: stagger the minute so load is distributed.
# Instead of this — fires simultaneously across all workers: 0 * * * * # Assign each worker a random minute: 23 * * * * ← worker A fires at :23 # Or spread with a step and offset: 7-59/30 * * * * ← fires at :07 and :37 each hour
Silent failure
Cron doesn't alert you when a job fails. By default, a failed job produces no notification, no log entry in your monitoring stack, nothing — it simply doesn't run. Jobs can silently stop for days before anyone notices. The standard fix is a dead man's switch: the job pings a health-check URL at the end of every successful run. If the ping doesn't arrive within the expected window, the monitoring service sends an alert. Services like Healthchecks.io and Cronitor provide this for free at low volumes.
Frequently asked questions
- What timezone does cron use?
- By default, cron uses the system timezone of the server. This can cause confusion when servers are in UTC but you're thinking in local time. Always specify your intent clearly — "9 AM UTC" rather than "9 AM" — and use a cron parser to verify the next scheduled run.
- What happens if a cron job is still running when the next one starts?
- By default, cron doesn't track whether a previous run finished — it will start a new instance regardless. This can cause overlapping runs. Use a lock file or a job queue system if you need to prevent concurrent execution.
- Where are cron jobs defined?
- On Linux/Mac, user-level cron jobs are defined in a crontab file (edit with crontab -e). System-level jobs go in /etc/cron.d/, /etc/cron.daily/, etc. Modern cloud platforms (Vercel, AWS Lambda, Railway) have their own cron scheduling that doesn't require a crontab.