arrow_backAll posts
Engineering·6 min read

Cron job monitoring: know when a scheduled job didn't run

Backups, imports and nightly reports fail silently — there's no error when a job never starts. Heartbeat monitoring turns that silence into an alert, in one line of shell.

T
Tom, Founder
A paper planner open on a desk next to a cup of coffee

Most monitoring watches for something bad happening: an error, a slow response, a failed request. Scheduled jobs fail the other way. When the nightly backup doesn't run, nothing happens at all — no error, no log line, no alert. You find out weeks later, when you need the backup.

Heartbeat monitoring (sometimes called a dead man's switch) flips the logic: instead of watching for failure, it waits for a sign of success, and alerts when that sign doesn't arrive in time.

How heartbeat monitoring works

  • You create a cron monitor and tell it how often the job runs — every five minutes, every night at 2 AM, every Monday.
  • Zharp gives you a unique URL.
  • Your job calls that URL when it finishes successfully.
  • If the call doesn't arrive by the time it's due, plus a grace period, Zharp opens an incident and alerts whoever is on call.

The grace period covers jobs whose length varies: a backup that normally takes ten minutes but sometimes takes forty shouldn't page anyone at ten past.

One line in your crontab

The simplest version adds the ping after your command, joined with && so it's only sent when the job exits successfully:

0 2 * * * /usr/local/bin/backup.sh && curl -fsS --retry 3 https://api.zharp.io/api/v1/ping/YOUR_TOKEN > /dev/null

--retry 3 keeps a brief network hiccup from turning into a false alarm, and -fsS keeps the output quiet unless something goes wrong.

Measure how long it took, and why it failed

A job can also report when it starts and how it ended. Ping /start first, then send the exit code when it's done — 0 is success, anything else is recorded as a failure with that code:

PING_URL="https://api.zharp.io/api/v1/ping/YOUR_TOKEN"
curl -fsS --retry 3 "$PING_URL/start" > /dev/null
/usr/local/bin/backup.sh
code=$?
curl -fsS --retry 3 "$PING_URL/$code" > /dev/null

Now you see how long each run took, and a job that started but never finished stands out from one that never started at all.

It works anywhere a job runs

Because the job only has to make an HTTP request, the same monitor covers a Linux crontab, a Kubernetes CronJob, a GitHub Actions schedule, a Windows scheduled task or a queue worker that should process something every few minutes. There's nothing to install.

What to monitor first

  • Backups — the job you'll only need on your worst day.
  • Data imports and syncs — stale data looks like correct data until someone checks.
  • Billing and invoicing runs — silent failures here cost money.
  • Certificate renewal — see why SSL certificates still expire.
  • Cleanup jobs — disks fill up slowly, then all at once.

The cron monitor docs have ready-made examples for GitHub Actions, PowerShell and sending the end of the job's log with each ping.

Try it on your own services

The Free plan includes 25 monitors, alerts to every integration and a status page. No card needed.

Start for freearrow_forward