Published Updated
"The site is down" is rarely one fact. A request crosses name resolution, a TCP connection, a TLS handshake, and an HTTP exchange, and each of those can fail in a way that looks identical from a browser and completely different from a terminal. A useful availability check tells you which stage failed and how long each stage took, because that is what narrows the search from the entire stack to one component.
Check the complete request path
Start by writing down the exact URL, including scheme, host, port if it is non-default, and path. Then check the stages in order rather than jumping to the HTTP response. A name that does not resolve and a name that resolves to a host which refuses the connection are two entirely different incidents, but both produce the same browser error page.
The reason stage matters more than status is that each stage implicates a different team and a different system. DNS failures point at the zone, the delegation, and the TTL of a record someone changed. Connection failures point at firewalls, security groups, and whether a process is actually listening. TLS failures point at the certificate chain and the names on it. An HTTP status means every layer underneath already worked, which is enormously useful information even when the status itself is 500.
Site Check performs the request from this site's servers rather than from your browser, so it answers a different question than reloading the page: it tells you whether the site is reachable from a network that is not yours. That distinction is exactly what you need when a colleague can load a page and you cannot.
Read down until you find the symptom you have. The last column is the next place to look, not a guess at the cause.
| Stage | Symptom | What it already proves | Look at next |
|---|---|---|---|
| DNS resolution | NXDOMAIN, SERVFAIL, or no answer | Nothing beyond the name existing | Delegation, zone contents, a record changed inside its TTL, registrar status |
| TCP connect | Connection refused | The host is reachable and answered | Whether the process is listening, on which port, and on which address family |
| TCP connect | Connect timeout, no packets back | Nothing — the request vanished | Firewall and ACL rules, security groups, routing, a regional block |
| TLS handshake | Expired certificate, name mismatch, protocol or cipher error | The server is up and accepting connections | Chain completeness, the SAN list, SNI, minimum TLS version |
| HTTP response | 2xx | The whole path works end to end | Content and correctness, not availability |
| HTTP response | 3xx | Something answered and wants you elsewhere | The redirect target, loops, scheme and host mismatches |
| HTTP response | 403, 404, 429 | The server answered and deliberately rejected the request | WAF or geo rules (403), routing and rewrites (404), rate limits (429) |
| HTTP response | 500, 502, 503, 504 | An edge or origin answered; something behind it failed | Application errors (500), bad upstream reply (502), maintenance or overload (503), upstream timeout (504) |
A timeout and a 5xx are not the same outage
This is the single most useful distinction in availability checking. A connect timeout means no component in the path was willing or able to answer: packets were dropped silently, which is the behaviour of a firewall configured to DROP rather than REJECT, of a routing blackhole, or of a host that no longer exists. Nothing in your application logs will record it, because nothing in your application ever saw the request.
A 5xx means the opposite. Something answered — a load balancer, a reverse proxy, a CDN edge, or the application itself — and it produced an HTTP response to tell you it could not complete the work. That response has headers, and the headers usually identify which component wrote it. A 502 says the component in front received an invalid or empty reply from the thing behind it. A 504 says the thing behind it did not reply in time. A 503 usually says the component in front knows the backend pool is empty or is deliberately shedding load.
The practical consequence is where you look first. On a timeout, correlate with network and infrastructure changes and check whether the failure is region-specific, because a global timeout and a timeout from one network are different problems. On a 5xx, go straight to the logs of the component that emitted the response, and use the timing breakdown to see whether the failure was fast (an immediate rejection) or slow (an upstream that ran out of time).
- The curl timing fields are cumulative, not per-stage; subtract the previous value or you will misattribute the cost.
- A slow time_namelookup on the first request and a fast one afterwards is resolver caching, not a DNS problem.
- A large gap between time_appconnect and time_starttransfer is server-side work: that is the number to take to the application team.
$ curl -sS -o /dev/null \
-w 'dns %{time_namelookup}\ntcp %{time_connect}\ntls %{time_appconnect}\nttfb %{time_starttransfer}\ntotal %{time_total}\nstatus %{http_code}\n' \
https://www.example.com/
dns 0.031
tcp 0.048
tls 0.104
ttfb 0.712
total 0.718
status 200
# Each figure is cumulative from the start of the request, so:
# DNS 0.031
# TCP 0.017 (0.048 - 0.031)
# TLS 0.056 (0.104 - 0.048)
# server 0.608 (0.712 - 0.104) <- the real cost
# download 0.006 (0.718 - 0.712)Follow the redirect chain
A site can be perfectly healthy and still appear broken because of how it redirects. Every hop costs a full round trip, and a chain that crosses hostnames also drops cookies scoped to the previous host, which is a common cause of "the login works on one URL and not the other". Record the entire chain, not just the final status.
The failure modes worth checking for are a loop (two hosts redirecting to each other, which browsers abort after a fixed number of hops), a downgrade to plain HTTP anywhere in the middle, a chain that is longer than it needs to be because canonicalisation rules were added one at a time over years, and a redirect that points at a hostname whose certificate does not cover it. The last one shows up as a TLS error midway through a chain that started successfully.
Also check that the redirect codes are the ones you intended. A 301 and a 308 are both permanent, but a 301 historically allows a client to convert a POST into a GET while a 308 requires the method to be preserved. If an API client is silently losing a request body on redirect, that difference is usually why.
$ curl -sSIL http://example.com/docs | grep -Ei '^(HTTP/|location:)'
HTTP/1.1 301 Moved Permanently
location: https://example.com/docs
HTTP/2 308 Permanent Redirect
location: https://www.example.com/docs
HTTP/2 301 Moved Permanently
location: https://www.example.com/docs/
HTTP/2 200
# Four requests to serve one page. Hop 1 upgrades the scheme,
# hop 2 adds the www host, hop 3 adds a trailing slash.
# Collapsing this into a single 301 to the final URL removes
# three round trips from every cold request.Compare regions before you call it an outage
A check from one vantage point measures one path. When users in a particular country report a problem that nobody at the office can reproduce, the interesting question is whether the failure follows the destination or the origin network. Run the same URL from more than one network and compare the results side by side; if one region times out while the others return 200, the problem is in routing, peering, a CDN point of presence, or a geo rule, not in the application.
Latency deserves the same caution. A single measurement is noise. Congestion, a cold TLS session, an uncached DNS answer, and per-request scheduling all move the number, so take several samples and compare the distribution rather than the fastest or the most recent value. Consistent latency differences between regions usually mean the request is travelling to a distant origin instead of being served by a nearby edge — worth confirming by checking whether the response carries a cache-hit header.
Site Check is limited to 10 checks per visiting IP per UTC day, and that limit is deliberate: each check is a real outbound HTTP request to a third party, not a database lookup. Budget accordingly. Decide which URLs and which comparisons actually answer your question before you start, rather than reloading the same check and watching the number wobble.
Turn a check into an incident signal
A single manual check is evidence only if you record it in a form someone else can act on. Keep the full URL, the timestamp with timezone, the vantage point, the final status, the complete redirect chain, the per-stage timings, and any response header that identifies which component answered. That is roughly ten lines, and it converts "the site seems slow" into a statement an engineer can verify or refute.
Then correlate with what you own. External probes tell you about user-visible symptoms; origin logs tell you whether the request ever arrived. The most valuable finding in an incident is usually a request that appears in an external check and does not appear in any origin log, because it localises the fault to everything in between: DNS, the edge, the load balancer, or the network.
Be careful about escalating on one probe. Probes fail for their own reasons — the probe host's own network, its resolver, a transient rate limit, or the destination treating an unfamiliar source address as suspicious. Confirm from a second vantage point before declaring an outage, and be equally sceptical of a single successful check when users are still reporting failures.
- Only check destinations you are authorised to check; repeated automated requests against someone else's origin are load you did not ask permission to generate.
- Respect robots directives and published rate limits, and identify your probe honestly if you build your own.
- Treat a check that starts failing right after a deploy or a DNS change as correlated until proven otherwise — most availability incidents have a change behind them.
What to remember
- Check the stages in order — DNS, TCP, TLS, HTTP — because the stage that failed points at the system to investigate, while the status code alone does not.
- A connect timeout means nothing answered and nothing was logged; a 5xx means something answered, so go read that component's logs.
- Record the whole redirect chain, since every hop costs a round trip and a cross-host hop silently drops cookies scoped to the previous host.
- Take several latency samples from more than one vantage point before concluding anything, and remember curl's timing fields are cumulative.
- Site Check allows 10 checks per visiting IP per UTC day because each one is a real outbound request, so plan the comparison you need before spending them.