Skip to content

Outage tracker

How this check works

One honest description of what a status-line check can and cannot prove, so every reading on the outage tracker means exactly what it says and nothing more.

What we check

For each service on the outage tracker, we send a single HTTP GET request to a public endpoint from 10 independent regions (US East, US West, Europe, and Asia Pacific) on a fixed schedule. Each check records exactly four things:

  • Reachability. Whether a TCP connection and TLS handshake to the endpoint succeeded from that region, within our request timeout.
  • HTTP status code. The exact status line returned, if the connection succeeded.
  • Latency. Time from request start to receipt of the status line, per region.
  • TLS handshake success or failure. A distinct signal from an HTTP-level failure. A TLS failure often points to a network-path or certificate problem rather than an application-level outage.

We follow up to 3 redirects, re-checking each hop against the same safety rules we use for a customer's own monitor before following it. For most endpoints we never read past the status line: response bodies are not downloaded, stored, or inspected. A request that does not receive a response inside our timeout, or that fails at the network or TLS layer, is recorded as down.

For most services, every endpoint we check is a landing page, a status page, or a similar surface: a clean response there proves the server answered, not that the underlying product or account features actually work. A handful of services also expose a real, public, unauthenticated API endpoint, for example a package registry lookup or a repository API call, and where one exists we check that too. A service's own page states plainly which kind of check we run for it, "reachability verified" or "functional endpoints verified," and any endpoint marked "functional" in its endpoint list exercises real service functionality rather than just answering a request. Even a functional check does not cover every feature of a service: it is a stronger signal than reachability alone, not a full health check.

A small number of functional endpoints carry a declared expectation: a stated rule about what a genuinely healthy response's body, header, or status must look like, in addition to the status code alone. This exists for the handful of services whose only honest functional endpoint answers with the same status code (typically 403) whether the service is actually serving the request or a firewall in front of it is simply refusing us -- a case a status-line-only check cannot tell apart. For an endpoint with a declared expectation, we read up to 256 KB of the response body and check it against that stated rule, for example that a specific field is present in the service's own JSON error response. Nothing else is read, stored, or inspected, and no other endpoint's body is ever read. When the expectation is not met, the endpoint is recorded as down and the recorded reason names which check failed, exactly as a connection failure or a timeout would be. This is the same assertion mechanism a RealUptime Monitor customer can configure on their own checks; we did not build a second one for this tracker.

What we do not check

This is the complete list of what a status-line GET can honestly support, so it is worth being equally clear about what it cannot:

  • The service's actual user-facing experience. A user might see errors on checkout while our probe of the homepage returns a clean response. We check one endpoint, not the whole product.
  • Internal service health. Queue depth, database replication lag, or any backend state that is invisible from outside the service is outside what a public GET request can see.
  • Anything behind authentication. We do not log in, hold an account with any service on the tracker, or attempt a real transaction. A login page returning a normal response tells us the login surface is reachable, not that authentication or the systems behind it are working correctly.
  • Global coverage. We check from 10 regions: US-East, US-West, Europe, Asia-Pacific, US-Central, Canada, UK, Southeast Asia, Australia, and South America. We do not have a Middle East region yet. We say "monitored from 10 regions," never "global" or "worldwide," because that would claim coverage we do not have. We add regions by demand: the request control on every monitor form and on the pricing page is how that demand is counted.
  • A region a service doesn't operate in. Some services on the tracker only operate in part of the world, for example a delivery app available only in the United States. We do not probe a service from a region it does not actually serve: that would either waste a request against a market the service was never built for, or produce a reading that looks like a real signal but isn't. A service's own page marks a region it is not checked from as not monitored from that region, never as a blank, operational, or down reading we did not actually take.

How we read a response

Each service on the tracker has its own declared range of status codes we treat as healthy, since a redirect or a non-200 response can be entirely normal for one service and a genuine problem for another. A response outside that range, a connection failure, or a timeout is recorded as down.

A response code that refuses automated clients, such as 403, 406, 429 or 451, is recorded separately, as a filtered reading, rather than folded into down. That response tells us about our own request's reception, not necessarily about the service's health: a service can return one of these codes to automated traffic it does not recognize while working normally for everyone else, and a browser on a home connection gets a normal page from every one of them. A filtered reading never produces a verdict on a page: it renders as awaiting data, with a note explaining that the checks ran but were filtered, so a page never overstates what a block actually proves and never dresses our own reception up as the service's state.

A redirect loop, our request bouncing between the same two or three URLs until we give up following it, is also recorded as a filtered reading, not down. A real visitor's browser does not get stuck in the kind of consent or bot-check redirect chain that a request from our probe's network sometimes does, so a loop tells us about how our traffic is being routed, not that the service has failed.

A request that never receives a response before our timeout is usually recorded as down, since a real user would see the same thing: a page that never loads. There is one exception. If the same service has a second endpoint we check, and that second endpoint responded normally in the same round, we record the timed-out endpoint as filtered instead of down. A live sibling reading is evidence that our specific request was filtered, not that the service failed to respond to anyone. Without a healthy second reading to point to, a timeout stays down.

How we state the verdict

The headline on a service page is one of a fixed set of levels, composed from our own probe readings first and every other signal second, by the same code that answers the JSON endpoint and the MCP tools, so no surface of ours can say something another does not. Only a probe reading can make a page say down, partially down, degraded or partially degraded. Nothing else can. Two of the levels deserve their own explanation, because each one exists to avoid a claim we could not back.

Reachable, reports elevated. Our probes reached the service from every region we could read, and at the same time user reports and/or public posts about it being down are running above that service's own spike threshold. We say exactly that, in amber, and we do not call it down: reports are people saying something, not a measurement, and a crowd beside a clean reading is a contradiction worth showing rather than a reading to overrule. The sentence under the headline names which signal is elevated and, for reports, how many people filed one in the current window. The same spike is one of the things that makes us probe the service again outside its normal rotation, so the reading the headline rests on is never more than a few minutes old.

Awaiting data, when some regions answered and others could not be read. If the service's primary surface answered from some of the regions we check and gave us no usable reading from the rest, because a region's probe was filtered or no reading landed, the page says awaiting data, never operational. A clean reading from two regions is not an all-clear for four, and a missing reading is an absence of data, not an outage either. The sentence under the headline says how many regions answered and how many we could not read, and the per-region readings beneath it show which is which.

Every one of those levels is composed across each surface we check for a service, not read off a single page load. That is what lets a headline say partially down when a service's API is failing while its front-end still loads, and degraded when a surface answers but at several times its own seven-day median response time. Degraded only ever applies to a reading that answered: a surface that is down, or one that refused our probe, is a stronger and more useful thing to know, and we never soften either into “slow”.

We also record a response's CDN cache-status headers (cf-cache-status, age) alongside every reading, purely as corroborating context for later investigation; it never gates a verdict on its own.

How we identify ourselves

Every request the outage tracker sends carries a plain, honest User-Agent header identifying it as our probe and linking back to this page, so an operator who notices our traffic can see exactly what it is and why. We do not spoof a browser, use a residential proxy, or attempt to get past a challenge page. Some services allowlist declared, self-identifying monitors, which can reduce how often we get blocked. That is a reasonable outcome of being honest about who we are, not something we engineer around.

The exact header is realuptime-outage-checker/1.0 (+https://realuptime.io/outages/methodology). Every request is a single lightweight GET against one public surface per service per round: we never crawl a site, follow internal links, or fetch more than the one endpoint each service's catalog entry names.

We do not fetch or parse a probed service's robots.txt before probing it. That is a deliberate consequence of what this probe is, not an oversight: robots.txt governs a crawler that discovers URLs on its own and decides which ones to fetch, and we never discover anything. Every endpoint we hit is a single, fixed URL a person on our side chose and recorded in the service's catalog entry ahead of time, the same relationship an uptime monitor has with the one status page or health endpoint it is pointed at. We do not follow links, paginate, or expand our own request surface in response to anything a target returns. An operator who does want us to stop entirely does not need a robots.txt rule for it: the opt-out below removes us from the rotation outright.

Four of our regions run from static egress IPs that do not change under normal operation. If you operate a service on the tracker and want to allowlist our traffic instead of blocking it, or want to verify that a request claiming to be us actually came from our network, this is the complete list for those regions:

RegionIPv4IPv6
US-East209.71.108.32a09:8280:e618:1:0:15e:9f66:0
US-West209.71.96.992a09:8280:e633:1:0:15e:9f66:0
Europe209.71.109.1802a09:8280:e612:1:0:15e:9f66:0
Asia-Pacific209.71.107.822a09:8280:e625:1:0:15e:9f66:0

Our other 6 regions (US-Central, Canada, UK, Southeast Asia, Australia, South America) currently run on ordinary dynamic egress: the outbound address can change at any time, so there is no IP to allowlist for them honestly. Do not allowlist an address you previously saw from one of these regions; it is not guaranteed to stay ours. We publish the same static-vs-dynamic distinction in the machine-readable mirrors below, per region.

The same list, plus the cadence and User-Agent below, is published in machine-readable form at /api/v1/probe-ips (JSON) and /api/v1/probe-ips.txt (plain text), for a firewall allowlist, a bot-management tool, or a runbook to read directly rather than parsing this page.

Cadence tiers, the same three explained further down in “How often we check”: fast is every 2 minutes, standard is every 10 minutes, and slow is every 30 minutes, per region, per service.

Opt out. If you operate a service listed on the tracker and want it removed from our probe rotation entirely, email support@realuptime.io naming the service. We respond within 72 hours and stop probing that entry; we do not require a reason.

Vendor-reported status

Where a service publishes its own machine-readable status feed, we poll it on a schedule and store what it reports, separately from our own measured readings. A service page shows the vendor's own claim, in their words, clearly attributed to them. We never let a vendor's claim change our own numbers, and our own numbers never change theirs: two labeled sources, side by side.

When the two disagree, we say so plainly and name both readings rather than asserting either one is correct. A disagreement can mean a partial or user-specific issue our simple check does not exercise, a difference in what each of us is actually probing, or a delay in one side updating. We do not have enough information to resolve that gap from outside, and we do not pretend otherwise. Not every service on the tracker publishes a status feed we can read this way; where one doesn't exist, its page simply shows our own reading with no vendor comparison.

User reports

A service page also lets you say you are having a problem, with no account and no sign-up. Those reports are a second signal, and we keep them strictly separate from what we measured: two counts, two visual languages, two sentences. Report volume never opens, extends or closes an outage in our record. Only our own probe readings do that.

Reports are unverified, and we label them that way everywhere they appear. Anyone can file one, we do not check whether the person filing it is affected, and the region on a report is the one the person chose. When the report control opens on a region already selected, that is a guess from your browser's time zone, not a detected location, and you can change it or leave it as “not sure”.

We call a rise in reports a spike only when it is both unusual against that service's own trailing baseline and large enough in absolute terms to mean anything. A service almost nobody reports on cannot produce a meaningful spike from a handful of reports, so instead of drawing a dramatic line through noise we say “not enough reports to say”. On quieter services that is what you will see most of the time, and it is the honest reading rather than a gap.

We store no IP address on a report. What we keep is a one-way hash of your address mixed with the service name and a salt that rotates daily, so the same visitor looks different on every service page, and once that salt is deleted the hash cannot be traced back at all. Raw reports and their salts are deleted after seven days; only the counts remain. There is no comment box anywhere in this flow, deliberately.

How often we check, and what makes us check early

Every service has its own probe cadence: every 2 minutes for the ones people search for most during an incident, every 10 minutes for the bulk of the tracker, and every 30 minutes for the long tail. The page always shows when the last round actually ran, so you never have to infer freshness from the cadence.

On top of that schedule, four things can make us probe a service early, out of its normal rotation: a spike in user reports, a spike in third-party chatter, the service's own status feed declaring a new or worsening problem, and one of our own regions returning its first failed reading. Any of those schedules one extra round for that service, from every region we watch it from, within about a minute. A first failed reading is re-checked within five seconds.

This is the one place a signal we did not measure touches our probing, so it is worth being exact about what it does and does not do. A signal causes a measurement. It is never itself evidence, it never appears in the verdict, and it cannot open, extend or close an outage in our record: only a probe reading does that. The most a wave of fabricated reports can achieve is to make us go and look at a URL we already probe, once, and then publish what we saw. Each service can be made to look at most once every five minutes this way, whatever the volume behind the signal.

Where a signal did cause an extra probe, the service page says so, with the time it ran and what it found, in the third-party chatter block.

Feeds

Every service page publishes a feed of its own measured outage events at /feed.atom and /feed.xml (RSS 2.0), for example /outages/github/feed.atom. There is also one feed across the whole tracker at /outages/feed.atom. Every entry says plainly that it is our own probe measurement, from which region, and never states or implies a vendor's own claim about itself.

Badges and history

Every service page also links to a full availability history page (/outages/<slug>/history, for example /outages/github/history): 90 days of per-region availability, a monthly summary, and the incident log. And to an embeddable uptime badge you can drop into a README, backed by the same readings and the same stale/no-data honesty rules as everything else on this page.

Why this exists

The outage tracker is a small, honest instrument: it tells you what we observed, when, and from where. It is not a substitute for a service's own status communications, and it is not a claim about anything we cannot actually measure. If you want this same set of checks running against a site you own, with alerting when something changes, you can set that up directly.

Writing about a reading, or building on the dataset behind one? Data access for press and researchers covers what is public, the keyless JSON endpoints and their rate limit, and how to cite a reading.