The failure mode nobody talks about: a scheduled task stops running and nothing tells you. Windows Task Scheduler shows a green “Ready” state while the underlying script has been silently exiting on a missing dependency for three weeks. A cron job on the home server survives an OS upgrade in the schedule but not in the environment, and the backup that was supposed to fire nightly stops writing files. The system does not think anything is wrong because nothing threw. The backup is just missing.
We tested the 7 best apps for catching silent scheduled task failures across Linux, Windows, and macOS in 2026. The list covers the dead-man-switch services that expect a ping from your job and alert when it goes quiet, the general uptime monitors that also handle push-mode heartbeats, the metric exporters that let you graph the pattern, and the local tools that turn the raw signal into an alert somewhere you actually read.
What to look for in a scheduled task monitor
Pick a tool that:
- Uses a dead-man switch, not just “check if the exit code was zero.” The whole point is that the job is not running at all.
- Handles schedule tolerance sanely. A job that runs at 03:00 should tolerate a few minutes of drift before alerting; a job that runs every minute should not tolerate hours.
- Sends alerts to a channel you check. Email is fine until the outage is on your mail server; layer at least one non-email channel (a push service, a Discord webhook, an SMS).
- Runs somewhere independent of the host it monitors. A monitor that dies with the box it watches is not a monitor.
- Does not require paying per job. Households often have twenty or thirty scheduled tasks; a per-job billing model turns household infrastructure into a corporate cost centre.
Quick comparison
| App | Best for | Approach | Self-hosted | Free tier |
|---|---|---|---|---|
| Healthchecks.io | Dead-man switch with self-hosted option | Push heartbeats | Yes | Yes, 20 checks |
| Cronitor | Full cron job telemetry with per-job stats | Push + wrapper | No | Yes, 5 monitors |
| Dead Man’s Snitch | The original scheduled-task heartbeat | Push heartbeats | No | Yes, 1 snitch |
| Uptime Kuma | Self-hosted uptime monitor with push mode | Pull + push | Yes | Free, self-hosted |
| Prometheus Node Exporter | Metrics for systemd timer status | Pull metrics | Yes | Free |
| systemd | Native failure detection and email on Linux | Native | Yes | Free |
| Gotify | Self-hosted push notification server | Push server | Yes | Free |
Why “the task ran” is not the same as “the task worked”
The mental model most schedulers use is “did the process finish?” and the mental model needed is “did the outcome occur?” A backup script that finished successfully because the source directory was empty is not a working backup. A sync that finished successfully because the network was offline and the retry loop gave up quietly is not a working sync. A rebuild-search-index task that finished successfully because the daemon was down and the client returned an empty response is not a working rebuild.
The fix is two-layered: the job sends a heartbeat only after it has done its actual work (not just after it has started), and the monitor alerts when the heartbeat goes missing. Nothing else in the schedule stack catches the “silently doing nothing” mode. Task Scheduler will not. Cron will not. Windows Event Log will not.
The apps
1. Healthchecks.io — best dead-man switch with self-hosted option
Healthchecks.io is the reference implementation of the dead-man-switch pattern. Every scheduled task gets a unique URL, the task curls that URL at the end of its successful run, and Healthchecks alerts if the ping does not arrive within the expected window. Per-check grace periods, ping-with-exit-code (so a curl $URL/fail marks the check as failed explicitly), and per-check schedules expressed as either a simple interval or a full cron expression. Slack, Discord, PagerDuty, Gotify, ntfy, email, SMS, webhook, and about twenty other alert channels.
Where it falls short: The hosted free tier caps at 20 checks; households with big automation surfaces will outgrow it. Self-hosting fixes that but adds a service to maintain.
Platforms: Any Linux/Docker host for self-hosted. Hosted tier works from anything that can make an HTTP request.
Download: Healthchecks.io install
Bottom line: The right default for scheduled-task heartbeats on a home server.
2. Cronitor — best full cron telemetry with per-job stats
Cronitor goes past the heartbeat and captures the full runtime picture — how long the job took, exit code, stdout and stderr, comparative graphs across runs, and alerting on any of those changing. Wrap the job in the Cronitor CLI or ping the URL directly at start, end, and fail. The dashboard is aimed at teams; a household using half the features will still get value from the runtime graphs alone.
Where it falls short: Hosted only — no self-hosted path. Free tier is 5 monitors, which fills up fast on a busy server.
Platforms: Any host that can make outbound HTTPS. Wrapper CLI for Linux, macOS, Windows.
Download: Cronitor download
Bottom line: The right pick when you want per-job runtime graphs and are comfortable with a hosted service.
3. Dead Man’s Snitch — best the original heartbeat service
Dead Man’s Snitch popularised the pattern and remains one of the easiest ways to catch a silent failure. Create a snitch, get a URL, have the job hit that URL, get an email if the URL is not pinged inside the interval. That is the whole product. When “does anything need to be more complicated than this?” is the correct question, Dead Man’s Snitch is the honest answer.
Where it falls short: Free tier is one snitch — that is enough to protect one critical job and no more. Feature depth trails Healthchecks and Cronitor.
Platforms: Any host that can make outbound HTTPS.
Download: Dead Man’s Snitch signup
Bottom line: The right pick when the “backup did not run” alert is the only outcome you need to protect.
4. Uptime Kuma — best self-hosted uptime monitor with push mode
Uptime Kuma is the self-hosted uptime monitor that grew a proper push-mode alongside its HTTP and TCP probes. Point-and-click UI, most alert channels people care about, per-check status pages, and the same “check pushed within X seconds” model as Healthchecks. If the home server already runs Uptime Kuma for the media stack, adding cron job heartbeats to the same dashboard costs a few clicks.
Where it falls short: Push-mode support is newer than the pull-mode probes and is where the rougher edges are. Less specialised at the cron-heartbeat use case than Healthchecks.
Platforms: Linux (Docker), Windows, macOS.
Download: Uptime Kuma install
Bottom line: The right pick when the household already runs Uptime Kuma and does not want another dashboard.
5. Prometheus Node Exporter — best metrics for systemd timer status
Prometheus Node Exporter ships a collector for systemd unit and timer state. Combined with Prometheus and Alertmanager, you can graph “when did this timer last succeed,” alert on “no successful run in the last N minutes,” and correlate with system-wide metrics (CPU, disk, network). This is the industrial-strength approach; overkill for a household, exactly the right shape for anyone already running Prometheus.
Where it falls short: Requires the whole Prometheus stack to be useful — that is real infrastructure, not a five-minute install. Systemd-specific for the timer collector; cron jobs need a different approach.
Platforms: Linux, Windows, macOS, FreeBSD.
Download: Prometheus Node Exporter releases
Bottom line: The right pick when Prometheus is already the metrics store on the home lab.
6. systemd — best native failure detection on Linux
systemd on modern Linux has more built-in failure handling than most cron migrants realise. A unit with OnFailure= triggers another unit when it fails, which can be a mail script, a webhook, or a script that pings Healthchecks. systemctl list-timers shows the schedule and last run, and systemctl status <unit> shows the exit code and log tail. For anyone already on systemd timers, half the monitoring is already in the box.
Where it falls short: Only tells you when the process failed, not when the outcome failed. A backup script that finished but did nothing useful looks green to systemd.
Platforms: Linux (systemd-based distros).
Download: systemd resources
Bottom line: The right minimum on any Linux server running systemd timers.
7. Gotify — best self-hosted push notification server
Gotify is the small Go server that turns any HTTP request into an Android push notification. On its own it does not detect failures; combined with any of the tools above, it becomes the way alerts actually reach a phone without depending on Firebase Cloud Messaging or a third-party notification service. Ideal for households where the alert channel needs to be as private as the servers being watched.
Where it falls short: Not a monitor by itself. Requires the Android app to be installed on the receiving phones; iOS support relies on ntfy or similar rather than Gotify’s own app.
Platforms: Linux (Docker), Windows, macOS, FreeBSD.
Download: Gotify install
Bottom line: The right last-mile push notification server for a self-hosted alerting stack.
How to pick the right one
- If you want a dead-man switch that works today: Healthchecks.io (self-host once it grows past 20 checks).
- If you want per-job runtime telemetry and are fine with a hosted service: Cronitor.
- If you only need to protect one critical job: Dead Man’s Snitch.
- If the home server already runs Uptime Kuma: Uptime Kuma.
- If Prometheus is already the metrics store: Prometheus Node Exporter.
- If the Linux server runs systemd timers and you want the built-in monitoring: systemd.
- If you want alerts to reach the household’s phones without going through a third-party push service: Gotify.
For most home labs, the working combination is Healthchecks (self-hosted) as the dead-man switch, wired into Gotify for phone push and email as the fallback. Anything running as a systemd timer gets an OnFailure= unit that pings the same Healthchecks endpoint on failure so the two signals correlate.
FAQ
What is the difference between a heartbeat and a health check?
A heartbeat is the job saying “I ran and succeeded.” A health check is a monitor probing the service to see if it responds. Heartbeats catch silent scheduled-task failures; health checks catch runtime service failures. You want both.
Where should I send the alerts?
Somewhere off the machine being monitored. Email is fine as a fallback but should not be the only channel — if the machine that runs mail is the machine that failed, the alert never leaves. Layer email plus a phone push (ntfy, Gotify, Pushover) plus a chat channel (Discord webhook, Slack) for high-priority jobs.
How do I add a heartbeat to a Windows Task Scheduler job?
Wrap the action in a small PowerShell script that runs the real task, checks the exit code, and calls Invoke-WebRequest against the Healthchecks or Cronitor URL only when everything succeeded. Task Scheduler’s own “run this on completion” hook does not distinguish between success and failure cleanly, so do it in the script.
Is systemd really enough for Linux monitoring?
For “did the process crash?” — yes. For “did the outcome happen?” — no. Combine systemd’s OnFailure= with a heartbeat that the job sends only after its real work finished for the full picture.
Should I still monitor cron itself?
Yes. Cron can be running and healthy while individual jobs quietly stop firing (a bad crontab syntax, a permission change, a missing user). Uptime Kuma or Healthchecks can also monitor cron’s own last-run time on a home server; if that goes stale, cron is what needs attention.