Learn the theory
Cron Jobs: Schedules, Overlaps & Missed Runs: how it works
4 min read · Updated
Cron runs commands on a schedule: every night, every five minutes, every Monday at 9. The syntax is tiny — five fields — but production cron jobs fail in predictable ways: a run takes longer than its interval and overlaps itself, the machine is down and the run is missed, or two fields combine in a way nobody expected. This lab shows the schedule, the timeline and the failure modes side by side.
In short
- A cron expression has 5 fields: minute, hour, day of month, month, day of week.
- Plain cron only checks the clock once a minute and has no memory: runs during downtime are lost.
- If a job takes longer than its interval, runs overlap unless you add a lock or skip-if-running policy.
- When both day-of-month and day-of-week are restricted, cron uses OR, not AND.
- Cron schedules are in the server's timezone (often UTC), and DST can skip or repeat local times.
The five fields
┌──────── minute (0–59)
│ ┌────── hour (0–23)
│ │ ┌──── day of month (1–31)
│ │ │ ┌── month (1–12)
│ │ │ │ ┌ day of week (0–7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * * command| Syntax | Meaning | Example |
|---|---|---|
* | every value | * * * * * every minute |
*/n | every n-th value | */5 * * * * every 5 minutes |
a-b | a range | 0 9-17 * * * hourly, 9 to 17 |
a,b,c | a list | 0 8,20 * * * at 08:00 and 20:00 |
a-b/n | range with a step | 0-30/10 * * * * minutes 0, 10, 20, 30 |
The day-of-month / day-of-week trap
If you restrict both day-of-month and day-of-week, standard cron fires when either matches. 0 0 13 * 5 is “midnight on the 13th, or on any Friday” — not “Friday the 13th”. The last preset in the lab prints the real run dates so you can see it.
When a job is slower than its schedule
Cron doesn't know whether the last run finished. A 7-minute job scheduled every 5 minutes starts a second copy before the first ends. Depending on the job, that can double-send emails, double-charge cards, fight over locks or exhaust the database.
| Policy | Behavior | Use when |
|---|---|---|
| Allow overlap | Start every tick regardless. | The job is safe to run concurrently. |
| Skip if running | Drop the tick if the previous run is active (use a lock file, flock, or a DB advisory lock). | Work is “latest state wins”, e.g. a sync or cleanup. |
| Queue | Run every tick, one after another. | Every tick must be processed. Watch for an ever-growing backlog. |
# skip-if-running with flock
*/5 * * * * flock -n /tmp/report.lock /usr/local/bin/build-reportMissed runs and catch-up
Classic cron only evaluates the current minute. If the machine is off, rebooting or the scheduler crashed at 03:00, the 03:00 run never happens and nothing records it. Options:
- `anacron` (or systemd timers with
Persistent=true) run a missed job once when the system comes back. - Job schedulers in a database or queue (BullMQ repeatable jobs, Sidekiq, Temporal, Kubernetes CronJobs with
startingDeadlineSeconds) persist the schedule. - Idempotent jobs that process “everything since last success” make a catch-up trivial and safe.
Timezones and daylight saving time
Cron uses the system timezone unless you configure one. Local-time schedules misbehave around DST: a job at 30 2 * * * may not run on the day clocks jump forward (02:30 doesn't exist) and some implementations run twice when clocks fall back. Most teams schedule in UTC and convert in the UI.
Production checklist
- Use locks or a queue so runs can't overlap unintentionally.
- Make jobs idempotent and resumable.
- Add jitter (a random delay) to avoid every service hammering the database at
:00. - Log start, end and exit status; alert when a job doesn't run (dead-man's switch).
- Set timeouts so a hung run can't block the next one forever.
- Prefer a real job queue when you need retries, backoff or visibility.
Frequently asked questions
- What does */5 * * * * mean in cron?
- Run every 5 minutes: the minute field
*/5means every fifth minute (0, 5, 10 …), and the other fields are wildcards. - What happens if a cron job takes longer than its interval?
- Cron starts the next run anyway, so two copies can overlap. Use a lock (flock, advisory lock) or skip-if-running logic if overlap is unsafe.
- Does cron run missed jobs after downtime?
- No. Standard cron only checks the current minute and keeps no record of missed runs. Use anacron, systemd timers with Persistent=true, or a persistent scheduler to catch up.
- Why does my cron expression with a day of month and a weekday run too often?
- When both fields are restricted, cron matches if EITHER the day of month OR the day of week matches. It is not an AND.
- What timezone does cron use?
- The system's timezone (often UTC on servers) unless a CRON_TZ/TZ setting or your scheduler specifies otherwise. DST changes can skip or repeat local-time schedules.
- When should I use a job queue instead of cron?
- When you need retries with backoff, concurrency control, visibility into failures, or work triggered by events. Keep cron as the trigger that enqueues jobs.