Quick Answer: Monitor cron jobs with heartbeat monitoring: each job sends an HTTP ping to a unique URL when it finishes successfully. The monitoring service knows your schedule and alerts you if the ping does not arrive within the expected interval plus a grace period. This catches silent failures that uptime checks on your homepage never will.
Why doesn't cron tell me when a job fails?
Cron runs your command and moves on. If the script exits with a non-zero code, cron may log it locally. If the server reboots at 2am and the job never runs, cron has nothing to report. If the job hangs for six hours and eventually gets killed, you might not notice until a customer asks where their invoice went.
This is the fundamental gap between uptime monitoring and scheduled task monitoring. An HTTP check on your website confirms the site responds. It does not confirm your nightly database backup ran, your invoice generator processed rows, or your cache purge fired on schedule.
Most teams discover a broken cron job weeks later, usually when downstream data is missing. By then the blast radius is much larger than if you had caught the first missed run.
What is heartbeat monitoring (and why is it called a dead man's switch)?
Heartbeat monitoring inverts the usual monitoring model. Instead of an external probe asking "is this service up?", your cron job tells the monitor "I finished successfully." The monitor watches the clock. If the expected ping does not arrive, it alerts you.
The older name, dead man's switch, comes from the same idea: if the operator stops signaling, something is wrong. For cron jobs, that means catching failures that leave no trace:
- The host was down during the scheduled window
- The cron daemon was not running
- The script crashed before reaching the end
- A deploy broke the script path
- The job ran but took so long it missed the next window
None of these show up on a homepage uptime check. All of them show up when a success ping stops arriving.
How do I set up cron job monitoring step by step?
Step 1: Create a heartbeat monitor for each critical job. Do not lump five unrelated crons into one monitor. Your invoice job and your log rotation job have different schedules and different failure impact. One monitor per job keeps alerts actionable.
In Overwatch, create a Scheduled check, set the expected interval (for example every 6 hours or daily), and configure a grace period that covers normal runtime plus buffer. You get a unique check-in URL.
Step 2: Ping on success, not at the start of the script. The most common mistake is sending a heartbeat before the work runs. If the script crashes halfway through, the monitor thinks everything is fine. Chain the ping after your command succeeds:
0 2 * * * /opt/scripts/backup.sh && curl -fsS --retry 3 --max-time 10 -X POST "https://your-checkin-url"
The && ensures the ping only fires on exit code 0. Use -fsS so curl fails quietly on HTTP errors, --retry 3 for transient network blips, and --max-time 10 so a stuck curl does not block your cron slot.
Step 3: Report failures explicitly. Waiting for a missed heartbeat works, but it is slow when the job runs on a daily schedule. Add a failure branch:
0 2 * * * /opt/scripts/backup.sh && curl -fsS -X POST "https://your-checkin-url" || curl -fsS -X POST "https://your-checkin-url?status=fail"
A fail ping pages you in seconds instead of waiting until tomorrow's window passes.
Step 4: Set grace period from observed runtime. Check your logs for how long the job actually takes under normal load. Grace should be peak runtime plus 30-50% buffer. A job that usually finishes in 15 minutes with occasional 25-minute runs needs at least 35-40 minutes of grace, not 5.
Step 5: Route alerts to a channel your team reads. Cron failures are not always page-worthy, but they should never go to a channel nobody monitors. Send critical job failures to Slack or PagerDuty. Send low-priority housekeeping jobs to a lower-priority channel.
What cron jobs should I monitor first?
Not every cron needs a heartbeat on day one. Prioritize jobs where a silent failure has customer or revenue impact:
- Billing and invoicing (missed run means unpaid invoices or double charges)
- Database backups (you only discover a broken backup during a restore)
- Data sync and ETL pipelines (stale dashboards, wrong reports)
- Certificate renewal scripts (Let's Encrypt cron failures cause outages weeks later)
- Cleanup jobs that prevent disk exhaustion (full disks take down everything)
Start with your top three. Add monitors for the rest as you build the habit.
How is this different from checking server uptime?
Server uptime monitoring answers: "Can I reach this machine or URL right now?" Heartbeat monitoring answers: "Did this specific task complete on schedule?"
| Signal | Uptime check | Heartbeat check |
|---|---|---|
| Server is online | Yes | No (server can be up while cron is broken) |
| Job ran on schedule | No | Yes |
| Job exited cleanly | No | Yes (with success/fail pings) |
| Works behind firewall | Needs inbound access | Yes (outbound ping only) |
Many outages are partial: the API is up but the nightly aggregation job stopped three days ago. You need both check types. Overwatch covers HTTP, TCP, TLS, and DNS uptime checks alongside scheduled heartbeat monitors in one dashboard, so you are not juggling separate tools for your web stack and your background jobs.
What are common mistakes with cron job monitoring?
Pinging before work completes. A heartbeat at the top of the script reports success even when the script crashes later. Always ping after exit code 0.
Grace period too tight. Setting 5 minutes of grace on a job that sometimes runs 40 minutes trains your team to ignore alerts. Measure first, then configure.
One monitor for many jobs. When the shared ping stops, you do not know which job failed. Separate monitors mean separate alert messages and faster debugging.
Ignoring slow runs. A backup that normally takes 10 minutes and suddenly finishes in 30 seconds probably did not back up anything. Track duration over time. A job that completes suspiciously fast is often a broken job that exited early.
Relying on cron email output. MAILTO still has a place for debugging, but email is not an on-call channel. Nobody reads cron mail at 3am. Wire heartbeats into the same alert routing as your production uptime monitors.
Frequently Asked Questions
What is heartbeat monitoring for cron jobs?
Heartbeat monitoring (also called dead man's switch monitoring) means your cron job sends an HTTP request to a monitoring service when it completes successfully. The service knows your schedule and alerts you if the ping does not arrive within the expected window plus a grace period. This catches jobs that never ran, crashed before finishing, or ran far longer than normal.
How do I know if my cron job failed?
Cron itself does not alert you on failure unless you wire up email or logging. The reliable approach is to append a curl command that pings a monitoring URL only on exit code 0, and a separate fail ping on non-zero exit. If neither success nor fail arrives on schedule, the monitor marks the job as silent and pages you.
What grace period should I set for cron job monitoring?
Set grace to your job's typical runtime plus a buffer. A daily backup that normally finishes in 20 minutes should use at least 30-45 minutes of grace. Too little grace causes false alerts during slow runs. Too much grace delays detection when the job never starts.
Can heartbeat monitoring detect jobs that hang?
A success-only ping detects hangs only after the grace window expires. For faster hang detection, send a start ping when the job begins and alert if no success ping follows within your maximum expected duration. Many teams use start plus success signals for anything that runs longer than a few minutes.
Do I need to install software on my server to monitor cron jobs?
No. Most heartbeat monitors only need curl or wget available on the server. You create a monitor, copy the ping URL, and add one line to your crontab or systemd unit. No agent, no open inbound ports, and it works for jobs behind firewalls because the server initiates the outbound request.
Silent cron failures are how small bugs become big incidents. Overwatch gives you scheduled heartbeat checks with configurable intervals and grace windows, success and fail ping URLs, and alerts to Slack, Discord, Teams, email, or any webhook. Monitor your web stack and your background jobs in one place. Get started free →