A cron job that fails loudly is easy to fix. The dangerous ones fail silently: the backup that stopped running three weeks ago, the invoice job that skipped a night, the cleanup task that quietly hit a full disk. This guide covers why cron jobs go quiet and how to catch them before your users do.
Why cron jobs fail silently
Cron was built to run commands, not to report on them. When a job breaks, cron usually tells nobody. The most common causes:
Environment differences. Cron runs with a minimal
PATH, so a command that works in your shell is not found.Server changes. A migration, a reboot or a new container image drops the crontab.
Overlapping runs. A slow job is still running when the next one starts, and both fail.
Lost output. Errors go to a local mailbox nobody reads.
Heartbeat monitoring in three steps
The most reliable fix is a heartbeat: the job pings a URL when it finishes, and you get alerted when the ping does not arrive on time.
Create a check in checkhost.io and copy its ping URL.
Add the ping to the end of your job.
Set the expected schedule and a grace period.
Example crontab
# run the backup at 02:00, ping only if it succeeds
0 2 * * * /usr/local/bin/backup.sh && curl -fsS --retry 3 https://checkhost.io/ping/your-check-id > /dev/null
The && matters: the ping only fires when the backup exits with status 0, so a failed run counts as a missed heartbeat.
Picking a grace period
Job runs | Typical duration | Suggested grace |
|---|---|---|
Every 5 minutes | Under 30 seconds | 5 minutes |
Hourly | 1–5 minutes | 15 minutes |
Daily | 10–30 minutes | 1 hour |
A good rule of thumb: set the grace period to about twice the job's longest normal run.
What to monitor first
Start with the jobs whose silence costs the most:
Database backups
Billing and invoice runs
Certificate renewals
Data syncs to third-party services