〉 Guides · Monitor cron jobs

How to monitor cron jobs

Cron does not tell you when a job stops running. A backup can fail every night for weeks before anyone looks. This guide shows the heartbeat pattern, which works with any monitoring tool and any language.

Why normal monitoring misses cron jobs

The heartbeat pattern (dead man's switch)

Turn it around: instead of watching for errors, expect a signal. Each time the job finishes, it calls a unique URL (a "ping"). The monitor knows the schedule. If no ping arrives in time, it alerts you. Silence is the alarm, so it also catches jobs that never ran.

Step 1: Create a check with the job's schedule

In your monitoring tool, create a heartbeat check and give it the same schedule as the job, for example 0 3 * * * (every day at 03:00), and the same timezone the server uses. You get a unique ping URL. Treat it like a password: anyone with it can send pings.

Step 2: Ping at the end of the job

Add the ping after the job, joined with &&, so it only runs when the job succeeds:

# m h dom mon dow  command
0 3 * * *  /opt/scripts/backup.sh && curl -fsS -m 10 --retry 3 -o /dev/null https://monitor.example/ping/YOUR-TOKEN

Inside a script, ping as the last line, after set -e so any failed step stops the script before it pings:

#!/usr/bin/env bash
set -euo pipefail
pg_dump mydb | gzip > /backups/mydb-$(date +%F).sql.gz
curl -fsS -m 10 --retry 3 -o /dev/null https://monitor.example/ping/YOUR-TOKEN

Step 3: Report start and failure too (optional)

Many tools accept extra signals. A "start" ping lets the monitor measure how long the job runs and notice a job that hangs. A "fail" ping alerts you right away instead of waiting for the deadline:

URL=https://monitor.example/ping/YOUR-TOKEN
curl -fsS -m 10 -o /dev/null "$URL/start"
if /opt/scripts/backup.sh; then
  curl -fsS -m 10 -o /dev/null "$URL"
else
  curl -fsS -m 10 -o /dev/null "$URL/fail"
fi

Step 4: Pick a grace period

The grace period is how long past the expected time the monitor waits before it alerts. Too short and you get false alarms; too long and you hear late.

Step 5: Send alerts where people will see them

Step 6: Test it

Run the ping by hand once to see it arrive. Then break it on purpose: comment out the job, or change the ping URL, and wait for the alert. A monitor you have never seen fire is one you can't trust.

curl -fsS -m 10 https://monitor.example/ping/YOUR-TOKEN && echo "ping sent"

The same pattern outside cron

Doing it with vizsu

Uptime by vizsu has heartbeat checks. You give the check a cron expression, a timezone and a grace period (at least 30 seconds), and Uptime gives you a ping URL that ends in /heartbeat/<token>. Copy it from the check.

curl -fsS -m 10 https://<your ping URL>          # success
curl -fsS -m 10 https://<your ping URL>/start    # job started
curl -fsS -m 10 https://<your ping URL>/fail     # job failed, alert now

You can also POST to <your ping URL>/<exit code>: 0 counts as success, anything else as a failure. A missed or failed ping opens an incident and alerts your channels, with escalation if nobody acknowledges.

Add a heartbeat →

Questions

What is a dead man's switch for cron jobs?+

The job sends a ping to a monitor every time it finishes. If the monitor does not get a ping on schedule, it alerts you. It catches jobs that fail and jobs that never start.

Why put the curl after && instead of on its own line?+

With && the ping only runs when the job exits with code 0. On its own line, the ping would be sent even when the job failed.

How long should the grace period be?+

A little longer than the job's normal run time plus some slack. For a 20-minute backup, 30 to 45 minutes is a sensible start.

Will a failing ping break my job?+

Use curl -m 10 so it can't hang. Because the ping is the last step, a failed ping does not undo the job's work; the monitor will alert you that the ping is missing.

Does this work for systemd timers and Kubernetes CronJobs?+

Yes. Anything that can make an HTTP request can send a heartbeat.

Related

Cron and heartbeat checks · Uptime · Business email on your own domain · All guides