
Uptime Checks vs Heartbeats: Which One Actually Catches Your Failure?
"Is the site up?" is really two questions: can the world reach you, and is the machinery inside still running? What each monitoring direction catches, what it misses, and the grid that diagnoses both.
Uptime Checks vs Heartbeats: Which One Actually Catches Your Failure?
"Is the site up?" sounds like one question. It's two, and they fail independently:
- Can the outside world reach you? (DNS, host, SSL, server crash)
- Is the machinery inside actually running? (cron jobs, backups, scheduled emails, the parts with no public face)
Uptime checks answer the first. Heartbeats — dead-man's switches — answer the second. Most tools sell you one and let you believe it covers both. It doesn't, and the failures each one misses are exactly the expensive kind.
Uptime checks: monitoring from the outside in
An uptime check is a robot visiting your site every few minutes, like a customer would. If it can't get an answer — connection refused, timeout, SSL error, HTTP 500 — the site is down for everyone, and someone should be paged.
What it catches: host outages, expired domains and certificates, crashed servers, broken deploys.
What it can't see: anything that doesn't have a URL. Your nightly backup doesn't serve a webpage. Neither does WP-Cron, your sync job, or the script that renews your SSL certificate. All of those can die for weeks behind a perfectly green uptime monitor — a cached page can even keep "the site" looking alive while PHP is on fire behind it.
Heartbeats: monitoring from the inside out
A heartbeat inverts the direction: the job itself reports in. Your backup script pings a check-in URL when it finishes; your cron pings every ten minutes. The monitor's question isn't "can I reach you?" but "have I heard from you lately?" Silence — not an error, just absence — raises the alarm. That's why it's called a dead-man's switch: it alarms precisely when the thing that should have spoken says nothing.
What it catches: dead cron, skipped backups, hung jobs, a site whose internals froze while the cache kept smiling.
What it can't see: whether customers can reach you. A backup can check in beautifully from a server whose public site lost its DNS an hour ago.
The grid that matters
| Uptime check says | Heartbeat says | It means | |
|---|---|---|---|
| Healthy | ✅ reachable | ✅ checking in | Carry on |
| Host down | ❌ unreachable | ❌ silent | Real outage — page whoever's on call |
| Zombie site | ✅ reachable | ❌ silent | Pages serve, but cron/PHP is dead behind the cache — the failure uptime tools sleep through |
| Job-only failure | ✅ reachable | ❌ silent (that job) | The backup didn't run. You want to know today, not on restore day |
The bottom rows are the point: the combinations diagnose what a single direction can't. Down and silent is an outage. Up but silent is rot behind the curtain.
One refinement worth knowing: verify-on-miss
Heartbeats riding WP-Cron have a famous false alarm: WP-Cron only runs when the site gets traffic, so a quiet night on a small site looks identical to death. FlowAlert closes this by probing the site over HTTP before paging anyone about a missed check-in — if the site answers, it waits politely; if it doesn't, you're paged with both facts. Quiet nights stopped crying wolf, and real failures still page fast.
What to actually set up
Both directions, on the things that earn them: an uptime check on every site whose downtime costs money, and a heartbeat on every job whose silent failure costs more — backups first, then cron, then anything scheduled that you'd otherwise verify by hope. In FlowAlert both route like any other alert — acknowledged on a phone, escalated if ignored — and both are included on every plan, because a dead-man's switch that goes quiet exactly when nobody's watching would be worse than none at all.


