Healthchecks.io Cron vs Uptime Kuma Push: Jobs That Look Alive After a Silent Fail

Diana Vos

Diana Vos

August 25, 2026

Healthchecks.io Cron vs Uptime Kuma Push: Jobs That Look Alive After a Silent Fail

A cron job can fail and still look alive. The script starts. It curls a ping at the top. It then copies nothing because the mount is empty. It exits zero because you did not set -e. Healthchecks.io got a heartbeat. Uptime Kuma’s push monitor got a ping. The dashboard is green. The destination folder is from March. Silent fail is the default shape of homelab automation. The product you pick only matters if you ping at the right moment with the right meaning.

There is already a shelf of “Kuma versus Healthchecks” feature lists. This is about jobs: backups, cert renewals, scrape scripts, the thing that must run every night and must not lie. If you came from the Kuma versus Healthchecks comparison on this site, keep both tools. Change where the curl sits. The older post is about hosting and UX. This one is about a script that compliments itself.

I still want Kuma on the HTTP surfaces: Forgejo, Vaultwarden, the router UI if I must. I want Healthchecks on the things that have no port: restic, certbot, the scrape that fills a SQLite. When I tried to represent restic as a Kuma HTTP monitor, I invented a fake status page that returned 200 from a wrapper. The wrapper was the silent fail. Do not invent HTTP to avoid a dead-man. Use the dead-man.

Pull versus push, said for cron

Uptime Kuma is great at pull: hit a URL, see if it is up. A cron box has no URL. You can add a push monitor and curl it. That works. It is a second-class citizen in an app that thinks in HTTP. Healthchecks is first-class dead-man: if the ping does not arrive in the window, you get mailed. That is the model cron needs.

Kuma can do it. Healthchecks is shaped for it. I use Healthchecks for jobs and Kuma for services. Two tools, two lies they catch. Kuma will not notice a backup that never ran unless you push. Healthchecks will not notice a website that is 500 unless you also probe it. Do not make one dashboard do both well if you will only configure one well.

A backup script that exited zero beside an empty destination folder

Where to put the ping

Ping at start means “cron fired.” The job can still fail. Ping at end means “script reached the last line.” The job can still have copied nothing. Ping at end with a failure URL / /fail means “I am telling you I broke.” That is the one I want for backups.

Healthchecks supports success, start, and fail URLs. Use start if you also want “it hung” (started, never finished). Use fail from the trap. Use success only after a verify: file exists, size > yesterday, canary string present. A success ping after restic backup without checking exit code is how March’s folder happens.

Kuma push is usually one URL. You can encode success by only pinging on zero. You lose hung-job detection unless you also have a timeout mentally. You can add a second monitor. You will not. Healthchecks’ start/success pair is why I still open their site for cron.

Silent fails the ping cannot see

Empty source. Wrong AWS key that still “succeeds” a dry path. rsync to a path that is a new empty disk. find | xargs that matches nothing. Docker compose that restarts a container and you ping anyway. These need a check, not a curl. I wrote about restic canaries. Same canary: a file you update in the source, assert it in the dest, then ping. If the canary is stale, send fail even if the tool exited zero.

Timezone and DST: Healthchecks grace periods are the whole game. A job that runs at 2:30 on DST night can look late. Cron on UTC. Document it. Kuma push timeouts have the same footgun if you think in wall clocks.

A phone showing a missed cron alert at dawn

Self-host versus their cloud for the dead-man

If Healthchecks is on the same NAS as the cron, the house dying takes the alerter. Same joke as Gotify on the NAS. Use hosted Healthchecks for the jobs that mean the house is down, or a VPS. Kuma on a VPS pulling the house is the service story. Kuma on the house receiving push from the house is the blast-radius story. I want the dead-man off-box.

Privacy: job names go to a vendor if you use their cloud. I can live with “backup-nas” on Healthchecks.io. I would not put a customer hostname in the check title. Self-host if that bothers you, and put the self-host off the NAS.

A script skeleton that does not lie as often

Start ping. Run the job with set -euo pipefail. Verify canary or row count. Success ping. On any exit, fail ping in a trap. Log the snapshot id. That is boring. Boring is how March stops happening.

Do not wrap this in a five-tool platform. A bash function and two URLs beat a pretty workflow you will not read at 6 a.m.

Notifications that teach you to ignore green

If every compose restart pings success, you will mute the channel and miss the backup. Job checks should be quiet on success if you want, and loud on miss. Healthchecks can integrate with the same ntfy/Pushover path I use for water leaks, but it should not share the emergency sound. A missed backup is morning-loud. A missed freezer is 3 a.m. Do not train the household to swipe away cron.

Flap is the other teacher. A job that is late every Monday because it waits on a lock will page you until you widen grace or fix the lock. Widening grace is how you miss a real skip. Fix the lock. Note the duration in the check. If the job takes 40 minutes, a 15-minute window is a lie you wrote.

Kuma’s pretty charts will not show “empty dest.” They will show uptime of a push. I glance at a file mtime in the same morning ritual as the dashboard. Two signals. One can lie.

Systemd timers versus crontab

Timers that do not start because the unit is disabled look like a missed ping — good. Timers that start and hit a oneshot that returns 0 on a no-op look alive — bad. OnFailure= can curl fail. Use it. Cron’s silent non-start (host down) is exactly Healthchecks’ job. The host-down case is why the checker cannot live only on that host.

Anacron on a desktop you shut at night will ping in bursts when you open the lid. Healthchecks will think you flapped. Either keep job hosts up or use a schedule that matches a machine that sleeps. Desktops are bad cron boxes. I said that about subnet routers. Same energy.

When Kuma push is enough

You already live in Kuma. You have three jobs. You will only ping on verified success. You accept no start/hang pair. Fine. Do not add Healthchecks for a religion. Add it when the job list grows or when you want schedules and grace in a UI that thinks like cron.

When you have fifteen jobs, Healthchecks’ tags, slugs, and quiet hours are worth the second login. Kuma’s UI will become a pile of push monitors you named “backup2.”

The close

Green means a URL was hit. It does not mean the job did the work. Healthchecks is shaped for dead-man cron. Kuma push can imitate it. Both lie if you ping too early or skip the canary. Ping after verify, fail on trap, keep the dead-man off the box that dies. The silent fail is the script. The dashboard only reports what you taught it to believe.

If you change one thing this week, move the ping below the verify and add a fail trap. Leave the brand debate for later. I have seen more data saved by that move than by switching vendors. The vendor is a mailbox. The script is the liar. Teach the script to confess. Then let Healthchecks or Kuma shout the confession from a box that is not on fire.

More articles for you