Loading live status…
Loading live status…
Every uptime number is an artifact of when somebody looked, who did the looking, and what happened when the looking failed. Four bugs from building isuptime, and what each one says about reading anyone's status page.
A status page looks like an instrument. Green dot, uptime percentage, a sparkline — the visual language of measurement. It is worth knowing that most of it is not measurement at all. A provider's status page is a publication: a statement, written by the company being described, about how that company believes it is doing.
isuptime reads 44 of those publications on a schedule and puts them on one screen. Building it has mostly been a series of discoveries that the hard part is not fetching the feeds. It is that every honest-looking number on a status page — ours included — is an artifact of three things: when somebody looked, who did the looking, and what happened when the looking itself failed.
Here are four bugs we shipped, and what each one turned out to be about.
The first version sampled every service when somebody loaded the page. This is the obvious design, and it is quietly circular: uptime became a record of our traffic.
A busy afternoon produced dense data. A quiet night at 3am produced an eighteen-hour hole — which the aggregate rendered not as "we do not know", but as nothing at all, silently averaging over the gap. The hours when nobody was watching are exactly the hours worth watching, and those were the hours we had no data for.
The fix is unglamorous: a scheduled poller every five minutes, and page views record nothing. Sampling driven by the schedule, not by traffic. The distinction sounds pedantic until you notice that a traffic-sampled uptime figure is partly a measurement of the site's own popularity.
It also forced an honest storage decision. Raw samples do not scale — 102 services at five-minute resolution is roughly 881,000 records a month. Daily rollups of {checks, ok, latSum, latCount} answer every question we actually ask for about 1,260 rows in the same period. Uptime is ok / checks over a rolling 30-day window, and nothing else is kept.
This is the one worth stealing the lesson from.
Production once displayed: "All systems operational. All 2 monitored services responded normally." We were monitoring 44. A cold serverless instance had opened 44 TLS connections at once, missed the render deadline on 42 of them, marked those 42 unreachable — and then reported cheerfully on the two that made it.
Two things were wrong, and they are different failures.
The first: a feed we could not read is not evidence that a service is fine. Unreachable had been folded in with operational when it should be its own state, excluded from the "all systems operational" claim and from the uptime history entirely. A checker that cannot reach GitHub's status page has learned something about itself, not about GitHub.
The second is subtler. Once one bad reading was cached, it was served to everyone for a full minute. Now a new reading may only replace a cached one if it reached at least 75% as many providers — a wreck of a fetch does not get to evict a healthy snapshot, though it is still served if there is nothing else, because a thin answer beats a blank page.
The general form: a monitoring system's failure mode should not resemble good news. If your checker's degraded state looks like a green dashboard, you have built something worse than no dashboard, because now people trust it.
Every status aggregator has a cold-start problem it does not talk about. A fresh instance has nothing cached, so the first visitor pays for a fan-out across every upstream feed and watches a skeleton while 102 providers are asked how they are.
The fix was to stop asking. The scheduled poller already knows — it swept everything a few minutes ago — so a cold render now serves the poller's reading and warms the live one behind it. First paint went from seconds to well under one.
But that trade has to be disclosed, and this is where most status pages quietly cheat. The reading being served is up to five minutes old. So the timestamp is the poller's, not the render's: the page says "last checked 10:41 UTC" rather than restamping the moment you happened to load it. A stale answer that says how stale it is remains useful. A stale answer wearing a fresh timestamp is a lie with a clock on it.
There is a second rule, and it is not optional. If the stored reading is more than eleven minutes old — two missed polls — it is ignored and the page fetches live. Without that, a dead scheduler silently becomes a frozen status page: every dot still green, every number still confident, nothing behind them. The whole benefit of the snapshot depends on the fallback that makes it expire.
The last one shipped this week, caused by the fix above.
A small badge in the header read "Connection lost — retrying" whenever the displayed data was more than 90 seconds old. That was a fair inference for exactly as long as every reading was taken by the request that rendered it: old data meant a failed fetch.
The snapshot change broke the inference without touching the badge. Now data is routinely four minutes old by design, and a perfectly healthy page greeted people with a red connection-lost warning on first paint.
The correction was to stop inferring. "Connection lost" now means the browser genuinely cannot reach our API — two consecutive failed requests, not one, so a single dropped packet does not flash red at everybody. Data that is simply a few minutes old gets a quiet, true "Updated 4m ago".
The bug is worth generalising: a proxy signal keeps reporting long after the thing it stood for has changed. Age stood in for connectivity, connectivity stopped being what age meant, and the badge kept confidently answering a question it could no longer see.
None of this is specific to us, which is why it is worth writing down. When you look at a status page — ours, Cloudflare's, AWS's, Slack's — four questions get you most of the way to knowing what you are reading:
We publish 102 status pages on one screen because comparing them is genuinely useful. We try to be clear that what we are showing you is 102 companies' own accounts of themselves, collected five minutes ago, by a checker that sometimes has bad days of its own — and that says so when it does.