Skip to content
Guide

Heartbeat monitoring, explained.

Normal monitoring asks “are you there?”. Heartbeat monitoring waits to be told. Why that catches the failures that make no noise, and how to set it up.

6 minute read · Updated

Most monitoring works by asking. A monitor requests your website and decides whether the answer looks healthy. That works for anything that can be asked: a website, an API, a server that answers on a port.

A lot of important work cannot be asked. A nightly backup, a scheduled report, a queue worker, a cron job that clears out old data. These run quietly in the background, and when they stop, nothing breaks loudly. Nobody is looking at the backup that did not run, until the day you need it.

Heartbeat monitoring turns the question around.

How it works

With a heartbeat, the job reports in. Each time it finishes, it sends a small request, a “check-in”, to a unique web address. The monitor knows when the job should have checked in. If the check-in does not arrive in time, something is wrong, and you are alerted.

The key idea is that silence is the signal. You do not need to know why the job failed to know that it did. A job that never started, a server that was switched off, a script that crashed halfway, a network that was down: all of them look the same from the monitor’s side. The check-in did not come.

A check that asks “are you there?” cannot see a job that was never scheduled. A heartbeat can, because it was expecting to hear from it.

The parts of a heartbeat check

  • A schedule. How often the job should check in: every five minutes, every night at 2am, every Monday.
  • A grace period. Extra time allowed before the job counts as late, because real jobs do not take exactly the same time every run.
  • A unique address. The URL the job requests to check in. Treat it like a password: anyone who has it can send a check-in for that job.

Between check-ins the check is either waiting, late (past its expected time but still inside its grace period) or down (past the grace period, or the job reported a failure). You are alerted when it goes down and again when it recovers.

What it catches

  • Jobs that never run. A changed crontab, a deleted scheduler entry, a server restart that lost the schedule.
  • Jobs that start but never finish. A hung process, a lock that is never released, a script that crashes before the last line.
  • Jobs that run but fail. A job can report its own failure the moment it happens, instead of waiting for the deadline.
  • Whole machines going quiet. A server that is off, a network that is cut, a service that has stopped.
  • Jobs that suddenly take far longer. A job that reports when it starts and when it ends gives you its run time, so a slowdown shows up as a trend.

Adding a heartbeat to a job

If the job runs from cron or a script, add one line at the end that requests the check’s address. Use && so the check-in is only sent when the job succeeded:

0 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 -o /dev/null https://pingvella.com/ping/your-check-uuid

If the backup fails, the check-in never happens, and the silence raises the alert. To see failures straight away, and to measure how long runs take, add a start signal and a failure signal too:

curl -fsS -m 10 -o /dev/null https://pingvella.com/ping/your-check-uuid/start /usr/local/bin/backup.sh curl -fsS -m 10 -o /dev/null https://pingvella.com/ping/your-check-uuid/$?

Ending the address with the job’s exit status means a non-zero exit is reported as a failure immediately. Laravel applications can use the scheduler’s own pingBefore, thenPing and pingOnFailure methods instead, and each check page shows the code ready to copy.

Websites can use heartbeats too

Heartbeats are not only for background jobs. If a website or service is on a private network, a monitor on the internet cannot reach it. Run the check from inside instead, and check in only when it succeeds. The silence when the site stops answering is your alert. The website monitoring page shows how.

Setting good schedules and grace periods

  • Set the schedule to match the job’s real schedule, not an approximation of it.
  • Make the grace period longer than the job’s slowest normal run. Too short and you will get false alarms; too long and real failures take longer to surface.
  • Keep one check per job. A check for “all my cron jobs” can only tell you that something went wrong, not what.
  • Pause a check during planned maintenance so it does not alert, and resume it afterwards.

Where to go next

Pingvella’s cron job monitoring is built on exactly this. Every account gets three heartbeat checks free, with alerts by email, Slack, Discord, Microsoft Teams, Telegram or webhook. For the website side of the picture, read why you need to monitor your website.

Start in a couple of minutes

Hear about it before your customers do.

Create a free account