Blog·Reliability

Your site returned 200 OK. Your checkout was still broken.

Uptime answers whether a server responded. It does not tell you whether the page a customer received could still do its job.

Your site returned 200 OK. Your checkout was still broken.

Everything looked green.

The server responded.

TLS was valid.

Latency was normal.

The homepage returned 200 OK.

And customers still could not buy anything.

That sounds contradictory only if we treat uptime as proof that a website works.

It is not.

Uptime tells us something narrow and useful: an endpoint responded.

Users experience something much larger.

They load HTML, JavaScript, stylesheets, fonts, images, API responses, third-party scripts and client-side application state. All of those pieces have to cooperate before a page can do the thing it was built to do.

A successful HTTP response is only the first door in a very long hallway.

The green checkmark problem

Traditional uptime monitoring usually asks a question like:

Did this URL return a successful response?

For many systems, that is exactly the right question.

If an API health endpoint returns 500, something is clearly wrong.

If DNS fails, something is wrong.

If the TLS certificate is invalid, something is wrong.

If the web server stops answering entirely, something is very wrong.

But modern websites can fail much later.

Consider this sequence:

GET /checkout           → 200 OK
GET /app.js             → 200 OK
GET /checkout.chunk.js  → 404

The document exists.

The server is alive.

The browser receives HTML.

But the JavaScript chunk responsible for rendering the checkout button never arrives.

The user sees a broken interface.

The uptime monitor sees green.

Both observations are technically correct.

Only one of them reflects the user experience.

A website is a dependency graph

A modern page is not a single response.

It is closer to a dependency graph.

The browser first receives a document, then discovers and requests everything the page depends on.

That may include:

  • JavaScript bundles
  • CSS
  • images
  • fonts
  • API endpoints
  • authentication state
  • feature flags
  • third-party services
  • analytics
  • payment SDKs
  • maps
  • embeds
  • lazy-loaded modules

The page can successfully load at the network level while a critical node inside that graph fails.

Sometimes the failure is obvious.

A giant hero image disappears.

Sometimes it is subtle.

A form renders but the submit handler never attaches.

A button is visible but does nothing.

A checkout modal opens but never completes.

A login page loads while the authentication API is returning errors.

An SPA shell renders while the content route fails silently.

All of these can happen while the main document remains healthy.

Why HTTP 200 is not the same as functional availability

There are several layers between "the server responded" and "the website works."

1. Network availability

Can the client reach the host?

This includes:

  • DNS
  • TCP connection
  • TLS
  • redirects
  • HTTP response

2. Browser execution

Can a real browser execute the page?

This introduces:

  • JavaScript runtime errors
  • failed bundles
  • CSP issues
  • hydration failures
  • dynamic imports
  • browser-only behavior

3. Interface integrity

Did the important elements actually render?

Examples:

  • checkout button exists
  • login form exists
  • pricing table appears
  • booking form is visible
  • navigation is usable

4. Visual integrity

Does the page still look like the accepted version?

Examples:

  • layout has not collapsed
  • hero is not shifted off-screen
  • text is not clipped
  • mobile layout is not overflowing
  • critical content has not disappeared

5. Transaction integrity

Can the user complete the actual task?

Examples:

  • sign in
  • buy
  • subscribe
  • book
  • submit
  • upload

Each layer catches a different class of failure.

None completely replaces the others.

Error pages can return 200 too

There is another strange failure mode.

Some applications return an error screen with a successful HTTP status.

For example:

<html>
  <body>
    <h1>Something went wrong</h1>
  </body>
</html>

Response:

HTTP/1.1 200 OK

From a protocol perspective, the request succeeded.

From a product perspective, the site failed.

This is one reason monitoring systems should not interpret status codes without context.

The browser result matters too.

Mobile can be broken while desktop stays perfect

Responsive interfaces add another layer of ambiguity.

A desktop monitor may show:

healthy

while a mobile viewport shows:

horizontal overflow
CTA outside viewport
menu cannot open
checkout button hidden

The same URL can produce two different user experiences depending on viewport, device behavior and responsive breakpoints.

That means "the website is working" may be true for one user and false for another.

What should a useful monitor actually observe?

A useful monitoring stack should separate signals instead of collapsing everything into one red or green dot.

At minimum:

HTTP

Record:

  • status
  • latency
  • redirect chain
  • final URL

TLS and DNS

Distinguish:

  • certificate failure
  • hostname mismatch
  • DNS resolution failure
  • timeout
  • connection refusal

Browser

Capture:

  • JavaScript errors
  • failed resources
  • document state
  • final URL
  • critical network failures

DOM

Check:

  • missing expected elements
  • error-page patterns
  • broken images
  • forms that no longer work
  • layout overflow

Visual state

Compare:

  • current screenshot
  • accepted baseline
  • meaningful changed regions
  • desktop and mobile separately

Recovery

A failure is only half the story.

Monitoring should also be able to determine when the page has genuinely recovered.

The important distinction: available vs usable

The cleanest way to think about this is:

Availability asks whether the system responded.

Usability asks whether the user can still complete the intended job.

Both matter.

If the server is down, you need to know.

If the server is up but the checkout button disappeared, you also need to know.

The uncomfortable failures live in the gap between those two statements.

That gap is where a lot of modern web breakage hides.

A green uptime graph is still useful

None of this means uptime monitoring is obsolete.

It is foundational.

HTTP checks are fast, cheap and excellent at detecting infrastructure-level problems.

The mistake is assuming they prove more than they actually do.

A successful HTTP response means:

something answered.

It does not necessarily mean:

the website still works.

And for the people using your product, that difference is everything.