Skip to main content

heartbeat checks

Find out when a scheduled job stops running

A cron job that stops running produces no error and leaves nothing to poll, because the thing you want to check is a job that is not there. A heartbeat reverses the direction: your job calls a URL we give it, and we tell you when the calls stop.

The failure nothing reports

A job that fails loudly is the easy case. It exits nonzero, something catches it, someone gets paged. The costly case is the job that stops being run at all, because a crontab was edited away or the container holding it no longer starts. There is no process left to fail, so nothing is reported, and the dashboard stays as green as it was while the job still worked. GitLab found their nightly backup that way, months late.

A period and a grace, set to what the job really does

You say how often you expect the ping and how late it may be before it counts as failed. A job that runs hourly with a ten-minute grace flips to failing ten minutes after the missed run, and the alert follows once the confirmation count is met. Set the period to how often the job actually runs, not how often you wish it did: a period shorter than the real cadence means every run is already late when the next one starts, and the monitor flaps all night for a job that is fine.

You do not have to get the period right first time

Once five gaps between successful pings are on record, the monitor compares what you declared against what the job really does, and says so when the two disagree, in either direction. An hourly job earns that verdict the same day and a nightly one after about five days. A period set too tight pages you for nothing. One set too loose leaves a dead job unnoticed for longer than it needs to be.

Say more than "alive"

The bare URL says the job reached the end. A path segment after it says what the ping means. Calling /start before the work times the run. If you pass the exit code instead, a nonzero one fails the monitor straight away rather than waiting out the period, which is the difference between hearing about it at 03:05 and at 04:15. The first 4 KB of a POST body is kept as that run's output, so piping the end of the log in puts the exit code and the lines around the failure together, instead of on a machine you have to go and find.

The job that started and hung

A plain heartbeat cannot see this one. The job began, hung, and will never ping again. Pairing /start with a finish gives the run a duration, and a max run time then catches it while it is still hanging. Without that you wait out the whole period before anything is said, which for a nightly job is a day.

The ping URL is a credential

Anyone holding it can mark the job healthy, which means anyone holding it can keep a real outage invisible. It spreads by design into crontabs, CI config and runbooks, so it needs rotating when it leaks or when someone who knew it leaves. Rotate from the monitor page or the API and the monitor keeps its incidents, history, share links and status-page placement. The old URL keeps working for 24 hours by default, because a URL that dies instantly does not alert, it just goes quiet. Watch when the old one was last used and end the overlap early. If it genuinely leaked, end it straight away.

Run it beside the checks watching your front door

A heartbeat knows one thing, whether your job reported in. It can never tell you your website is down. It sits in the same monitor list as the HTTP, TLS and domain checks watching the front door, and it reaches the same status page and the same alert channels. Heartbeat is one of the eight check kinds here, not a separate tool to run.

A nightly backup, reporting for itself

curl -fsS $URL/start          # before the work

./nightly-backup.sh > backup.log 2>&1
code=$?

tail -c 4000 backup.log | curl -fsS --data-binary @- "$URL/$code"

FAQ

How do I monitor a cron job?
Create a heartbeat monitor, which mints a ping URL, and call that URL at the end of each successful run. Appending curl -fsS $URL to the job is usually the whole change. You set how often you expect the ping and how late it may be, and the monitor alerts when the calls stop arriving.
Why do cron jobs fail without alerting anyone?
Because a job that is never run produces nothing to catch. Error alerting fires on a job that runs and fails. It cannot fire on a crontab that was edited away, or on a container that stopped starting. There is no request to watch and no exit code to read, so a heartbeat has to come from the job itself.
What period and grace should I use?
The period is how often the job actually runs, not how often you would like it to. A period shorter than the real cadence means every run is already late when the next one starts, and the monitor flaps all night for a healthy job. Once five gaps between successful pings are on record, the monitor compares your declared period against the real one and tells you when they disagree, which for an hourly job is the same day.
Can it catch a job that starts and then hangs?
Yes, with a start signal and a max run time. Call /start before the work, finish with the exit code, and the run is timed. A job that started and will never finish is caught while it is still hanging rather than a whole period later.
Can I see why the job failed?
Yes. Pass the exit code on the finishing ping and POST the log with it. The monitor keeps the first 4 KB of that body, so pipe the end of the log in and the last failure carries the exit code beside the lines around it, read on the monitor page instead of on the machine that ran it.
What happens if the ping URL leaks?
Rotate it from the monitor page or the API. Anyone holding the URL can mark the job healthy, which means they can keep a real outage invisible. Rotation keeps the monitor's incidents, history, share links and status-page placement. The old URL keeps working for 24 hours by default so nothing goes silently quiet, and you can end that overlap immediately when the URL really leaked.

At a glance

  • Direction your job calls us
  • Signals start, success, fail, exit code
  • Run output POST body kept per run
  • Late job period plus a grace window
  • Ping URL rotatable, 24h overlap
  • Price to start free, no card

Links

Start in under 5 minutes.

Start free

features · pricing · notes