1Step-by-Step Breakdown
Who Actually Calls a Health Check. A health check endpoint isn't for humans manually checking a browser — it's polled automatically and frequently by infrastructure: a container orchestrator (Kubernetes), a load balancer, or an uptime monitor, each using the response to make an automated decision about whether to route traffic to, or restart, a given instance.
Liveness vs. Readiness: Different Questions. These answer genuinely different questions: liveness asks "is this process still running and not deadlocked?" (a failure triggers a restart), while readiness asks "is this instance currently able to serve traffic correctly?" (a failure just removes it from the load balancer's rotation, without restarting it) — conflating the two causes either unnecessary restarts or traffic sent to a broken instance.
A Naive "Always 200" Health Check Is Worse Than None. A health check that simply returns 200 OK unconditionally — common when it's added as an afterthought — provides zero actual signal: an instance can be completely unable to reach its database and still report itself as healthy, causing an orchestrator to keep routing traffic to (or never restart) a genuinely broken instance.
What a Readiness Check Should Actually Verify. A readiness check should verify the specific dependencies this instance genuinely needs to serve requests correctly — typically a database connection and any critical downstream service — but deliberately NOT every dependency in the system, since an unrelated, non-critical service being down shouldn't take a healthy instance out of rotation.
Timeouts Within the Health Check Itself. A health check that queries a database with no timeout can itself hang indefinitely if that database is slow rather than fully down — turning a health check into another point of failure. Every dependency check inside a health endpoint needs its own short, strict timeout, independent of the endpoint's own overall response time budget.
Graceful Shutdown and Readiness. When a process receives a shutdown signal (SIGTERM, e.g. during a deploy), it should immediately start reporting itself as NOT ready — removing it from load balancer rotation — while still finishing any in-flight requests, before actually exiting. This prevents new requests from being routed to an instance that's about to disappear.
Kubernetes Probe Configuration. In Kubernetes specifically, livenessProbe and readinessProbe are configured with distinct endpoints, intervals, and failure thresholds — getting the initialDelaySeconds and failureThreshold wrong is a common cause of pods being killed during normal (but slightly slow) startup, mistaking legitimate startup time for a genuine failure.
What is the practical difference between a liveness check failing versus a readiness check failing in an orchestrated environment like Kubernetes?
- →Liveness failure triggers a restart; readiness failure just removes the instance from traffic rotation without restarting it
- →They trigger the same response — both remove the instance from rotation
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Proper Readiness Checks Prevent Traffic Being Routed to a Broken Instance Mid-Task
When a readiness check correctly removes a struggling instance from rotation before it serves a broken response, it prevents a user mid-way through a multi-step flow (like a long form) from being routed to that broken instance and losing their progress — a cost that falls disproportionately on users relying on assistive technology.
SEO Implications
- 1
Correct Health Checks Directly Prevent User-Facing Downtime During Deploys and Incidents
A readiness check that promptly and accurately reflects an instance's true ability to serve traffic is one of the most direct mechanisms preventing users (and search engine crawlers) from ever hitting a broken or overloaded instance in the first place.
Best Practices
Implement distinct liveness and readiness endpoints, never one endpoint serving both purposes
They answer fundamentally different questions with different consequences — conflating them causes either unnecessary process restarts or traffic sent to a genuinely broken instance.
Report not-ready immediately on SIGTERM, before beginning graceful shutdown of in-flight requests
This stops new traffic from being routed to an instance that's about to disappear, while still allowing already-in-progress requests to complete normally.
Frequent Bugs
Pods or instances are repeatedly restarted by the orchestrator shortly after a normal deploy, even though the application eventually starts successfully.
This is a classic liveness probe initialDelaySeconds misconfiguration — the probe is checking before the application has finished its normal startup sequence, and the orchestrator mistakes legitimate startup time for a genuine failure. Increase the initial delay to comfortably exceed typical startup time.
Real-World Examples
Fixing a Meaningless Health Check That Masked a Real Outage
During a database outage, a load balancer continued routing traffic to instances whose /health endpoint unconditionally returned 200, causing every request to fail with a 500 error while the load balancer believed all instances were perfectly healthy. Replacing the endpoint with a real readiness check that verified the database connection (with a strict timeout) let the load balancer correctly detect the outage and stop routing traffic within seconds of the database going down.
app.get("/health/ready", async (req, res) => {
res.sendStatus(await checkDb() ? 200 : 503);
});