Monitoring 6 min read

Heartbeat Monitoring vs Uptime Checks: When to Use Which

Uptime checks ask your service whether it is up; heartbeats wait for your job to say it ran. How each works, what each misses, and how to combine them.

An uptime check pulls: a monitoring service sends a request to your website or API on a schedule and alerts you when the answer is wrong or missing. A heartbeat pushes: your job or service sends a request to the monitoring service each time it runs, and the alert fires when that request doesn’t arrive. Use uptime checks for anything people reach over the network, and heartbeats for work that runs on a schedule or has no public address. Most setups need both.

The two are easy to confuse because both end in “alert when something is wrong”. They see different failures, though, and using one where you need the other leaves a blind spot that only shows up when something breaks.

How an uptime check works

The monitoring service is the client. Every minute, or at whatever interval you choose, it requests a URL, pings a host or opens a port, and judges the answer: the status code, the response time, a keyword in the page, the certificate. If the check fails, and a second check confirms it, you get an alert. This is a form of synthetic monitoring: a robot does what a visitor would do.

  • It catches: a site or API that is down, slow, answering with errors, showing the wrong content, or broken by an expired certificate or a DNS change. Everything a visitor would run into.
  • It misses: anything that doesn’t answer requests. A backup that didn’t run, a queue worker that hung, an import that failed at 02:00. The website stays up, so every check passes.

How a heartbeat works

Your job is the client. You tell the monitoring service when the job is supposed to run, and the job calls a unique ping URL when it finishes. If the ping is late by more than a grace period you choose, you get an alert. The idea is a dead man’s switch: silence is the signal. That is why heartbeat monitoring is also called push monitoring or dead man’s switch monitoring.

0 3 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 3 -o /dev/null https://app.uptimecheck.com/api/hb/your-token
  • It catches: jobs that didn’t start, crashed before the end, ran on the wrong schedule or, with a start ping, ran far too long. With an exit code in the ping, it also catches jobs that ran and failed.
  • It misses: whether anyone can reach your service. A job on a server can ping happily while the website on the same server answers 502 to every visitor.

Side by side

Uptime checkHeartbeat
Who sends the requestThe monitoring serviceYour job or service
Alert whenThe answer is wrong, slow or missingThe ping is late, or reports a failure
Needs a public addressYesNo, only outbound HTTPS
Set upA URL, host or portA schedule, a grace period and one request in the job
SeesWhat visitors and API clients experienceWhether background work ran and how it ended
Blind toWork that doesn’t answer requestsWhether anyone can reach the service

When to use an uptime check

  • Your homepage and the pages that earn money: checkout, sign-up, login.
  • Public APIs and webhook receivers, with checks on the status code and the JSON that comes back.
  • A health check endpoint that tests the database and other dependencies on each request.
  • Services on other ports, such as a mail server, with a port check.

The rule of thumb: if a person or another system calls it, check it from outside the way they do.

When to use a heartbeat

  • Cron jobs: database and file backups, nightly imports and exports, report generation, billing runs.
  • Scheduled tasks in other forms: a Windows scheduled task, a Kubernetes CronJob, a GitHub Actions workflow on a schedule, a serverless function on a timer.
  • Certificate renewal scripts and data syncs between systems.
  • Anything behind a firewall or NAT that can’t be reached from outside, but can make an outbound HTTPS request.

Long-running workers

A queue worker or daemon doesn’t run on a schedule, but it can still send a heartbeat. Ping from the main loop every few minutes and give the monitor an interval instead of a cron expression. If the loop hangs, the process is killed or the server reboots without restarting it, the pings stop and you hear about it. Ping from the loop that does the work, not from a separate thread, or a stuck worker will keep reporting that it is fine.

When you need both

Most real services have a front door and a back office. Monitor each with the tool that sees it:

  • An online shop: uptime checks on the homepage and checkout, and heartbeats on the nightly order export and the database backup.
  • A SaaS product: an uptime check on the API’s health endpoint, and heartbeats on the queue worker and the job that sends invoices.
  • An internal service: no public address, so a heartbeat from the service itself, plus uptime checks on the public pages that depend on its data.

One alternative is to expose job status through the health endpoint, for example by failing the check when the last backup is older than 25 hours. It works, but it couples your website’s uptime to your backups, so a late backup shows up as website downtime in your reports. A separate heartbeat keeps the two signals, and the people who get each alert, apart.

Getting the timing right

  • Uptime check interval: every minute for pages that earn money, since the interval is the longest you can stay unaware of an outage. Less critical pages can use a longer interval.
  • Heartbeat grace period: longer than the normal variation in when the job finishes. A backup that starts at 03:00 and takes 5 to 20 minutes, pinging at the end, needs at least 20 minutes of grace; 30 leaves room for a slow night.
  • Maximum run time: with a start ping, alert when a run takes far longer than usual. A hung job never sends its finish ping either, but this alert comes as soon as the limit passes.
  • Time zone: a cron schedule runs in the server’s time zone, often UTC. Give the monitor the same one, or daylight saving will make it expect the job an hour early or late twice a year. The cron expression tool shows when a schedule actually runs.

Common mistakes

  • Pinging at the start only. A job that starts and crashes still checks in. Ping at the end, or send both.
  • Pinging even when the job fails. backup.sh; curl … pings whatever happened. Use &&, or send the exit code so a failure is reported as one.
  • A ping that can hang the job. Give curl a timeout and retries (-m 10 --retry 3), so a slow network neither blocks the job nor loses the ping.
  • Using a heartbeat for a public site. A server that pings out only proves it can reach the internet, not that visitors can reach it.
  • Monitoring the cron daemon instead of the job. The daemon can run fine while one job fails every night. Each job that matters gets its own heartbeat.

More on the heartbeat side in how to monitor cron jobs and how to prevent missed cron tasks.

Both in one place with Uptimecheck

Uptimecheck runs both kinds of monitor in the same account, with the same alert channels and incident history.

  • Uptime monitoring: HTTP(S), ping and port checks as often as every minute from Stockholm, Sweden, with each failure confirmed by a second check before an alert. HTTP checks can test the status code, a keyword, JSON fields and headers.
  • Cron job monitoring: a crontab expression in your time zone, daylight saving included, or a simple interval; a grace period from 1 minute to 6 hours; /start pings with a maximum run time from 1 minute to 24 hours; /fail or the exit code to report how a run ended; and the job’s output, posted with the ping, shown in the alert.
  • Limits: Start includes 15 uptime monitors and 10 cron jobs, Professional 100 and 50, Business 250 and 150. See pricing.

To set one up, see how to monitor a cron job with a heartbeat and the cron job ping examples for Laravel, Kubernetes, GitHub Actions, systemd and Windows. For disks and memory on the server underneath, add server monitoring.

Watch the front door and the back office. Try Uptimecheck free for 14 days, no credit card required.

Questions

What is the difference between heartbeat monitoring and uptime monitoring?

Uptime monitoring sends requests to your service and checks the answers. Heartbeat monitoring waits for your job to send a request each time it runs, and alerts when it doesn’t arrive on time.

What is a dead man’s switch in monitoring?

Another name for a heartbeat monitor: it acts when a regular signal stops. Your job pings on every run, and silence past the grace period triggers the alert.

Can I monitor a cron job with an uptime check?

Not directly, since a cron job doesn’t answer requests. You could expose its last run time on a health endpoint, but a heartbeat is simpler and keeps job failures out of your website’s uptime numbers.

Do heartbeats work behind a firewall?

Yes. The job only makes an outbound HTTPS request, so it works from servers without a public address, as long as outbound traffic to the ping URL is allowed.

Keep reading

Guides 7 min read

How to Build a Health Check Endpoint (and Monitor It)

A health check endpoint tells monitors and load balancers whether your app can serve requests. What to check, how to keep it fast and safe, code for Laravel, Express and Flask, and how to monitor it.

Read

Downtime is obsolete.

Set up your first monitor in under a minute, or look around the live demo first.

14-day free trial · No credit card required