Cron Job Monitoring: Get Alerted When a Cron Job Stops
Published:2026-11-08
Failure alerts from cron only fire when a job runs and fails. To catch a job that never ran because the server was down, the crontab line was removed, or the job hung, use a heartbeat, also called a dead man's switch: the job checks in after each success, and something outside alerts you when a check-in is late. Services such as Healthchecks.io do this, and so does nodd heartbeat, which alerts an iPhone.
Failures that failure alerts miss
Nightly backups and reports are often set up to send an email when they fail. That setup cannot see these cases:
- The server is down, or cron did not come back after a reboot
- A migration or config change removed or commented out the crontab line
- The job hangs and never finishes, and later runs pile up behind it
- The mail setup or alert command is broken, so the failure alert itself never goes out
None of these produce a failure event, so an alert that fires on failure stays silent. You find out the backups stopped weeks ago on the day you need to restore one.
How a heartbeat (dead man's switch) works
Flip the logic. The job checks in with an outside service every time it succeeds, and the service watches for the next check-in. If it does not arrive in time, you get an alert. This is called a heartbeat or a dead man's switch.
- The job sends an I am alive check-in as its last step
- The monitor sets the next due time from an interval (say 24 hours) and a grace period (say 1 hour)
- If the due time passes with no check-in, it alerts. Whatever the cause, the missing check-in tells you
The monitor must run somewhere other than the job. If it lives on the same server, it goes down with the server.
Approaches without Nodd
cron's MAILTO
cron mails any output from a command to the crontab owner. MAILTO changes the recipient, and an empty value turns mail off.
MAILTO=ops@example.com
0 3 * * * /usr/local/bin/backup.sh
It needs nothing extra and you read the error output directly. But the server must be able to send mail, and it cannot see a failure with no output or a job that never ran.
Wrap the script and alert on the exit code
0 3 * * * /usr/local/bin/backup.sh || notify-failure.sh backup
Send a Slack message, an email, or a push notification when the exit code is not 0. You hear about failures right away, with the reason. Still, nothing arrives when the job never runs or hangs.
Healthchecks.io, Cronitor, and similar services
These services specialize in heartbeats. With Healthchecks.io, the job pings a URL, and you are alerted when the period plus the grace time passes. /start signals a start, /fail a failure, and an exit code appended to the URL reports the result. It supports cron expression schedules and is open source under the BSD 3-clause license, so you can host it yourself. Cronitor also uses run, complete, and fail check-ins plus a schedule to alert on missed runs and runs that take too long.
0 3 * * * /usr/local/bin/backup.sh; curl -fsS -m 10 --retry 5 https://hc-ping.com/<uuid>/$?
For run time tracking, cron schedules, and the number of integrations, these dedicated services are the most complete. If you run many jobs, look at them first.
A monitoring stack such as Prometheus
If you already run Prometheus and Grafana, export the time each job last succeeded and alert when it gets too old. Prometheus's own guidance says the key metric of a batch job is the last time it succeeded. No new tool is needed, but it assumes you operate the stack. You can forward those alerts to an iPhone with an inbound URL (see monitoring alerts on an iPhone).
Comparison
| Compared | Reports failures / Catches jobs that never ran / What you need |
|---|---|
| MAILTO | If there is output / No / A server that can send mail |
| Exit code alert | Right away / No / Somewhere to send alerts |
| Healthchecks.io, Cronitor | Yes, with /fail or similar / Yes, including cron schedules / An account, or your own server |
| Monitoring stack alert | Depends on your metrics / Yes / A Prometheus-style setup |
| Nodd | Yes, with nodd send / Yes, by interval and grace seconds / An iPhone and the Nodd app |
Monitor with nodd heartbeat
Nodd is an iPhone app that receives notifications and questions from scripts and CI, and it can watch heartbeats. Install the CLI, run nodd login and scan the QR code with the app, or set a send key in NODD_KEY. Then run nodd heartbeat at the end of the job.
0 3 * * * /usr/local/bin/backup.sh && /usr/local/bin/nodd heartbeat nightly.backup --every 86400 --grace 3600
NAMEnames the heartbeat: up to 128 characters of letters, digits, and. _ : ---everyis the number of seconds until the next check-in, from 60 to 2,678,400--graceis the extra seconds to wait after that. It defaults to 10% of--every- The command prints the next due time
- If the next check-in does not arrive within
--everyplus--graceseconds, the channel gets a high priority alert. When check-ins resume, you get a recovery notification
With &&, the check-in goes out only when the backup succeeds. A failure, a job that never runs, and a hang all show up as a missing check-in. In the app, Heartbeat monitoring in the channel details shows each name, the last check-in, and whether it is OK or Missing. See the Manual.
The example is a job that runs daily at 03:00. If its run time varies, add that variation to --grace.
Alert right away on failure
With a heartbeat alone, you learn about a failure only after the due time passes. Send an alert as soon as the exit code is not 0 to hear about it sooner.
#!/bin/sh
# /usr/local/bin/backup-job.sh
NODD=/usr/local/bin/nodd
if /usr/local/bin/backup.sh; then
"$NODD" heartbeat nightly.backup --every 86400 --grace 3600
else
code=$?
"$NODD" send "Nightly backup failed" --kind alert --level high \
--alert-key nightly.backup --field exit=$code
exit $code
fi
0 3 * * * /usr/local/bin/backup-job.sh
An alert sent with --alert-key can be resolved once you fix the problem.
nodd resolve nightly.backup --note "Re-ran the backup by hand"
cron's PATH is often different from your interactive shell, so use the full path to nodd. nodd login saves the send key in ~/.config/nodd/config.json for the user who logged in. If the job runs from another user's crontab, log in as that user or pass NODD_KEY.
Use the API
Where you cannot install the CLI, call the API directly. interval is required, from 60 to 2,678,400 seconds. grace is 0 to 2,678,400 seconds. If omitted, it is 10% of interval and at least 60 seconds.
curl https://api.nodd.blipdrop.net/v1/heartbeats/nightly.backup \
-H "Authorization: Bearer $NODD_KEY" \
-H "Content-Type: application/json" \
-d '{"interval": 86400, "grace": 3600}'
It answers 200 with name and the next due_at. When you retire a job, stop its heartbeat, or it will keep reporting the job as missing.
curl -X DELETE https://api.nodd.blipdrop.net/v1/heartbeats/nightly.backup \
-H "Authorization: Bearer $NODD_KEY"
DELETE answers 204. You can also tap the row in the app to stop it. Managers, Owners, and Admins can do this.
Things to watch
- Monitoring is based on interval and grace seconds. There are no cron expression schedules, so jobs that run only on weekdays need care when you pick the interval. If you have many of those, a service with cron schedules fits better
- There is no start signal or run time tracking. A hung job shows up as a missing check-in
- Each channel can have 20 heartbeats. Check-ins do not count toward the monthly limit. The
nodd sendon failure counts as a regular message - Missing check-in alerts are high priority, so they come through during quiet hours
- The Free plan is one member, one device, and 10 channels. Use a Team plan when people take turns on call
FAQ
- Are failure alerts from cron enough?
- No. When the server is down, the crontab line is gone, or the job hangs, there is no failure event, so no alert fires. Add a heartbeat that checks in after each success and alerts when check-ins stop.
- What is a dead man's switch for cron jobs?
- It is a monitor that expects a check-in at a regular interval and alerts you when one does not arrive. For cron, the job sends the check-in as its last step.
- How should I set the grace period for nodd heartbeat?
- If you leave it out, it is 10% of --every. Set --grace longer to cover variation in run time and late starts.
- What happens to the heartbeat when I remove a job?
- The heartbeat stays and reports the job as missing. Call DELETE /v1/heartbeats/{name} or stop it from the list in the app.
- Should I use Healthchecks.io or Nodd?
- If you need cron expression schedules, run time tracking, or many integrations, a dedicated service such as Healthchecks.io fits better. If you want missing job alerts on an iPhone, in the same app where you answer approvals, Nodd fits.
Nodd delivers questions from scripts, CI, and AI agents to your iPhone, and returns your Face ID approval to the program that asked. There is a free plan.