What we check
For each service on the outage tracker, we send a single HTTP GET request to a public endpoint from 10 regions (US-East, US-West, Europe, Asia-Pacific, US-Central, Canada, UK, Southeast Asia, Australia, and South America) on a fixed schedule. Each check records exactly four things:
- Connection. 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 a failed check.
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, "front-door checks" or "front-door and live API checks," 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 passing says an API answered, not that the service works for you, and it is 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. This is 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 check is recorded as failed 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 our check of the login surface passed, 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, passing, or failing 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 a failed check.
A response code that refuses automated clients, such as 403, 405, 406, 429 or 451, is recorded separately, as a filtered reading, rather than folded into a failed check. 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. 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. 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 a failed check. 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. 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 a failed check. We cannot tell whether a user would see the same. 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 failed. 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 a failed check.
Every failed reading is stored. An outage from our checks opens only when checks fail from two or more distant regions, meaning regions on different continents. One region failing, or two regions on one continent failing, is never published. When one region fails 5 or more unrelated services at the same time, the fault is in that region's own network path, not in those services. We open no outage for them from that region, and its reading shows as awaiting data until the region recovers.
An outage with no live vendor incident behind it stops counting as an outage after 6 hours. If our checks still fail after that, the event shows only on that service's own page, labeled as unconfirmed. After 48 hours with no vendor incident, we treat our check as broken and say we cannot currently read the service.
An event that fails these rules is retracted, not deleted. It stays in our record and is listed on the corrections page, with the reason it was retracted.
What a pass shows, by kind of check
Every service page has a block called "What our check can and cannot see". It names which of nine kinds the service's check is, says what a pass of that kind shows and what it does not, and prints the host we check. The kind is stated for each service from the address we check and the way it answers, not from any reading, and it changes no verdict, event, alert or count. A service whose kind has not been stated shows no block. The block is also in the page's Spanish, Portuguese and German versions, and the English pair is in the API answer and the MCP output as check_evidence.
- Live data. A pass means the service returned real data from its own backend, with the content we expect. It does not show that every feature, account type or region works, or that sign-in is healthy.
- API route. A pass means a public route of the service's API answered our request normally. We do not check what it returned, so it does not show that the data is right, that sign-in works or that the rest of the product works.
- Health route. A pass means the service's own health route reported that it is up. It does not show that pages, sign-in or the features people use work; a health route can stay green while they fail.
- Sign-in wall. A pass means the service's servers answered with the sign-in refusal they give any request that is not signed in. It does not show that sign-in works or that anything behind the sign-in wall responds.
- Error answer. A pass means the service's servers answered our request with the error they give a request that carries no account or valid input. It does not show that sign-in works or that any real request succeeds.
- Discovery document. A pass means the configuration document the service publishes, such as an API or sign-in description, loaded. That document is usually static or cached, so it does not show that the endpoints it describes are answering.
- Public page. A pass means the service's public web page loaded and answered normally. It does not show that the product, the API or sign-in behind it works; a page can load from a cache while the product is down.
- Redirect only. A pass means the service answered with a redirect to another address. It does not show that the address it points to loads, or that anything behind it works.
- Bot challenge. A pass means the service's front door answered, even though it asks automated visitors to prove they are people. It does not show what a real visitor would see, because our check cannot get past that challenge.
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. The same code 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 checks failing, checks failing in some regions, 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.
Checks passing, reports elevated. Our checks passed from every region we could read, and at the same time user reports and/or public posts about a problem are running above that service's own spike threshold. We say exactly that, in amber, and we do not call it failing: 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 checks passing. 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 checks failing in some regions 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 whose check fails, 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.
When a service's own status feed works
A service's own status feed works when we read it successfully within the last 45 minutes. We read each feed about every 10 minutes, so one failed read does not change anything, and a feed we have stopped reading successfully stops counting after 45 minutes. While it works, what the vendor declares leads. The service page, the badge, the JSON answer, the MCP tools, the chat lookups, the browser extension, the feeds and the stack pages all open with the vendor's statement, in its own words and attributed to it, with the time of our last successful poll. Our check readings are still taken and still shown, under their own label, as our regional reading beside the statement. That reading is never counted as a second outage, and it never changes what the vendor says.
Which incidents count. An incident the vendor rates minor, major or critical is a declared outage. An incident rated no impact is shown as an incident, and is not an outage. Maintenance is never an incident.
An incident the vendor has not marked resolved stops being shown as live after 72 hours. The page says so rather than leaving it up. It says the vendor still lists an incident opened on that date, says when the vendor last updated it, and says that we do not show it as live. An incident the vendor has not resolved that two reads in a row no longer list is not shown as live either.
Some things are not shown for such a service, because they would be built from our probe events and would read as a clean record. These are the probe event log, the permanent probe event records, the month by month summary, the outage-credit calculator, and the last-outage line. The vendor's status page has its incident history, and the vendor's declared record is listed on the history page. When the feed stops working, the service reads by our checks alone again, by the rules in the sections above.
How an alert is made
For a service whose own status feed works, every incident the vendor reports at impact minor, major or critical gets its own alert when it opens and its own alert when the vendor reports it resolved. This holds even when another incident of the same service is already open, and whether or not an alert from our checks is open.
An incident first listed at no impact or as maintenance alerts at the moment it becomes minor, major or critical. A later change of impact inside the same incident, down to no impact or maintenance or back up, sends nothing more and does not close it. An incident the vendor resolves and later reports again under the same name is a new incident and sends again.
The closing email says what happened, in one of four ways.
- The vendor resolved it.
- The vendor no longer lists it on its status page (it removed it).
- It was never resolved, has gone 72 hours since it started, and our last successful read of the vendor's status page still listed it, so the email says we are closing our alert after 72 hours and gives the time of the vendor's last update.
- It has gone 72 hours and we can no longer read the vendor's status page, or our last successful read did not list it, so the email says we cannot tell whether the incident ended and that it closes the alert we sent on that date.
The closing email goes only to people who received the opening one. An incident rated no impact or maintenance sends nothing until it is rated higher. Two other cases send nothing either. One is an incident the vendor last touched more than 6 hours before we first saw it, which is history rather than news. The other is an incident that was already live when this alert first ran, however long ago the vendor last touched it.
Each alert is recorded for each recipient, channel and endpoint, so a retry after a failure does not, in normal operation, send a second copy. The email says it is the vendor's own statement from its status page, with our regional reading beside it when that reading has something it can state.
For a service whose status feed we cannot read, we email when our checks fail from two or more distant regions, and again when they pass, by the rules in the sections above. When a service's feed stops working, alerts from our checks resume for it at once; a closing email from our checks is sent only if its opening email was.
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 it and recorded it in the service's catalog entry ahead of time. It is 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.
Our probes do not run from fixed addresses. Every region uses ordinary outbound egress that can change at any time, so there is no IP list to allowlist, and an address you saw from us before is not guaranteed to stay ours. To recognise our traffic, match the User-Agent above.
The User-Agent, the regions and the cadence below are published in machine-readable form at /api/v1/probe-ips (JSON) and /api/v1/probe-ips.txt (plain text), for 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 check readings. A service page shows the vendor's own claim, in their words, clearly attributed to them. When that feed works, the claim leads the page, as described above, and our reading sits beside it under its own label. We never let a vendor's claim change our own numbers, and our own numbers never change theirs: two labeled sources, side by side, with the vendor's first.
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. The same visitor looks different on every service page. 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. They are 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 at /feed.atom and /feed.xml (RSS 2.0), for example /outages/github/feed.atom. For a service whose own status feed works, its entries are the incidents the vendor declared, each attributed to the vendor. For any other service, its entries are our probe events. There is also one feed across the whole tracker at /outages/feed.atom. Every probe-event entry says plainly that it is our own 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 history page (/outages/<slug>/history, for example /outages/github/history): 90 days of per-region check results, a monthly summary, and the probe event log, or, for a service whose own status feed works, the vendor's declared record. And to an embeddable 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. For a service whose own status feed works, the badge shows the vendor's word, not a figure from our checks.
Asking about one country
Every service page also has a page per country we hold a probe in (/outages/<slug>/in/<country>, for example /outages/github/in/uk), answering the question with that country's own reading now and over the last 24 hours, city named, and how the other regions read for contrast.
There is a page for each of the eight countries our probes sit in and none for any other country, however often it is searched. We have no machine in India, so we cannot tell you whether our checks of a service pass from India. A page that answered anyway from the nearest probe would be exactly the kind of claim this whole instrument exists to avoid.
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.