🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

Health Checks

Implementing liveness and readiness endpoints that orchestrators and load balancers actually rely on.

Total XP: 0|💻 backend XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

Select an unlocked node to view details root

🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

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

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

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

THE BUG

Pods or instances are repeatedly restarted by the orchestrator shortly after a normal deploy, even though the application eventually starts successfully.

THE FIX

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);
});

Interview Prep

Pascual Vila

Pascual Vila

Full-Stack Software and AI Engineer

Full-Stack Software and AI Engineer with 6 years of experience building enterprise-grade web applications across React, Angular, Node.js, and Python. Recently completed a Master's in AI Development specializing in LLMs, RAG, and AI agent architectures, and currently builds enterprise systems that integrate AI and Digital Twins to optimize industrial and logistics processes.

LinkedIn ↗
Common Pitfalls & Errors

The Error //

Implementing a health check that unconditionally returns 200 OK regardless of actual application state

// Wrong: no actual signal app.get("/health", (req, res) => res.sendStatus(200)); // Correct: verifies what actually matters app.get("/health/ready", async (req, res) => { res.sendStatus(await db.ping() ? 200 : 503); });

The Solution //

This provides zero real signal to the orchestrator or load balancer — an instance that has completely lost its database connection still reports itself as perfectly healthy, so traffic keeps being routed to (or the instance is never restarted despite) a genuinely broken service. A meaningful health check must actually verify the critical dependencies it relies on.

The Error //

Querying a dependency inside a health check with no timeout of its own

// Wrong: no bound on how long this can hang await db.query("SELECT 1"); // Correct: strict, short timeout independent of the check await db.query("SELECT 1", { timeout: 2000 });

The Solution //

If the dependency being checked (like a database) is slow rather than fully down, an unbounded check can hang the health endpoint itself indefinitely — turning the health check into an additional point of failure, and potentially causing the orchestrator's own probe to time out in a way that behaves unpredictably.

Continue Learning