Why cron jobs fail silently — and how to find out
System cron has no idea whether your job succeeded. Here's why scheduled jobs fail without a trace, and the patterns that fix it.
There’s a particular kind of outage that’s worse than a loud one: the silent kind. A scheduled job stops working, nothing alerts, and weeks later you discover the damage — an empty backup, a billing run that never fired, a search index frozen in time. This post is about why that happens and how to stop it.
Cron fires and forgets
The fundamental problem is that Unix cron is a launcher, not a supervisor.
It runs your command at the appointed minute and moves on. It doesn’t care
whether the command exited 0 or 1, whether it hung forever, or whether it printed
a stack trace. There is no built-in notion of success, failure, or “this should
have run an hour ago and didn’t.”
So a job can fail in all the usual ways — a dependency is down, credentials expired, the disk filled, a deploy changed a path — and from cron’s point of view, nothing happened.
The three failure modes nobody catches
- It ran and failed. The script started but exited non-zero. Cron doesn’t notice; at most it emails root’s local mailbox, which nobody reads.
- It hung. The job started and never finished, holding a lock or leaking memory. The next scheduled run may not even start.
- It never ran. The server rebooted, the crontab was edited wrong, or the timezone shifted under DST. The job simply isn’t firing — and absence is the hardest thing to notice.
The first two need the job to report its outcome. The third can’t be detected on the box at all, because the thing that would tell you is the thing that’s broken.
The fix: heartbeats and execution records
Two patterns close the gap.
Heartbeats move the “did it run?” question off the machine that might be down. Your job pings an external service when it finishes; if the ping doesn’t arrive on schedule, the service alerts you. Crucially, this catches the “never ran” case — silence is the signal.
# at the end of your job
curl -fsS https://ping.steadycron.com/<your-ping-token>
Execution records capture each run’s outcome — status, duration, output — so “did the 3am job succeed, and what did it return?” has an answer days later.
Where SteadyCron fits
SteadyCron does both. It can run your HTTP jobs with retries and timeouts, recording every invocation, and it can monitor the cron you already run via heartbeats — alerting on missed, failed, and stuck runs across email, Slack, Discord, Telegram, and webhooks.
If you’ve ever found out about a broken job from a customer instead of a dashboard, that’s the problem we built it to solve.
Start free or read the heartbeat monitoring guide.