200 OK but the Website Is Broken: What Uptime Checks Miss
A successful document response can hide a failed checkout or an unusable interface. Build a monitoring plan around the tasks your visitors need to complete.
A successful response is only the first checkpoint
A shop can serve its homepage successfully while its Pay button remains disabled. The server delivered a document; the customer still cannot place an order. Start an investigation by separating those two observations instead of treating a green availability check as proof that the whole site works.
HTTP 200 describes the response to a particular request. It does not certify every script, dependency or business action that follows. The distinction is consistent with HTTP response semantics (opens in a new tab). A status-only check is useful evidence about reachability, but it answers a narrower question than “can a customer complete their task?”
In an isolated Chromium fixture, a page returned 200 and displayed a checkout button. Its script then threw an exception and the button stayed disabled. A second fixture kept the same successful document response but enabled the button. The transport signal alone could not distinguish them; a browser assertion could.
Map each failure to the signal that can reveal it
Avoid adding checks simply because they are available. Start with the customer-visible failure and choose the smallest observation that would expose it.
| Failure after a release | A useful additional signal | What that signal still misses |
|---|---|---|
| A script throws before the menu initializes | Browser runtime errors and menu interaction | Errors reached only by another route or account |
| The stylesheet disappears | Asset response checks and a screenshot comparison | A layout defect outside the captured area |
| Search returns an empty fallback | A known query and an expected result | The correctness of every search result |
| Login redirects back to login | A synthetic account completing the sign-in flow | Permission problems for other roles |
| Scheduled exports stop arriving | A success heartbeat after export completion | Whether the exported business data is correct |
| Product pages acquire noindex | Robots metadata and header checks | Whether Google has already processed the change |
This table is a monitoring plan, not a claim that one browser visit covers every row. In particular, inspecting a public page is different from signing in, navigating an application and verifying a transaction.
Make browser readiness explicit
A page's load event can fire before its application is usable. Conversely, a page may keep a connection open after the interface is ready. Use a condition meaningful to the page rather than an arbitrary sleep.
For a project using Playwright Test, an initial non-destructive smoke test could look like this:
import { test, expect } from '@playwright/test';
test('catalog search is usable', async ({ page }) => {
const response = await page.goto('/catalog');
expect(response?.status()).toBe(200);
await expect(page.getByRole('searchbox', { name: 'Search products' }))
.toBeVisible();
await page.getByRole('searchbox', { name: 'Search products' })
.fill('monitoring handbook');
await page.getByRole('button', { name: 'Search', exact: true }).click();
await expect(page.getByRole('link', { name: 'Monitoring handbook', exact: true }))
.toBeVisible();
});
This is an adaptation template: configure a base URL, use your actual accessible labels and maintain a known fixture product. It was not run against a real store. The local experiment tested the simpler disabled-button failure. Playwright's web assertions (opens in a new tab) explain how assertions wait for an expected condition.
Keep a synthetic search query stable. If inventory changes naturally, a missing product is ambiguous evidence. Prefer dedicated non-sensitive test data and a test account with only the permissions needed for the check.
Keep probes from becoming customer actions
Do not routinely submit real orders, send customer emails or charge a payment method just to make a dashboard green. A production smoke test needs an explicit cleanup and side-effect policy. A safe search or read-only authenticated page is a better starting point than a destructive workflow.
When a transaction is necessary, use a controlled account and a supported test mechanism. Make it clear which environment is being exercised. A payment provider's sandbox transaction verifies the integration path in that sandbox; it does not establish that live settlement works.
The same care applies to evidence. Browser traces and screenshots can contain customer names, addresses, session details or private documents. Capture only what is necessary, restrict access and set a retention period. Redacting a screenshot later does not undo an earlier disclosure to a monitoring service.
Compare the monitor's experience with the user's
A passing probe from one location does not rule out a region-specific CDN issue. A logged-out browser does not represent a returning customer with old JavaScript in memory. A bot challenge can prevent inspection before the application is reached.
When an alert and a customer report disagree, record:
- The exact route and final URL, including unexpected redirects.
- Whether the browser was logged in, had consent stored or had an older tab open.
- The document status, failed asset responses and relevant runtime exception.
- The release identifier and time of both observations.
Treat “could not inspect” as a separate state from “inspected and passed.” An empty error list from an incomplete visit should not become evidence that the page is healthy.
Combine a release gate with ongoing observation
Before switching traffic, run a small set of critical checks against the candidate. After the switch, request the public entry point and confirm that the browser is using the expected release. Keep periodic monitoring running afterwards to detect later certificate, dependency or background-task failures.
DeployWatchers can add availability, JavaScript, visual and other website checks to that observation. Configure the checks that match your risk; do not assume that a public-page check includes a custom authenticated checkout journey. A short outage between scheduled probes may also go unseen.
The goal is a small set of complementary signals with clear meanings: the server responded, the page initialized, the layout remained usable and the critical task completed. When those signals disagree, their differences help locate the fault.
Catch problems after your next deployment
Monitor availability, browser JavaScript errors and visual changes with DeployWatchers.