In this lesson, you will learn how to distinguish between process vitality and service capability using health checks versus readiness checks.
In a resilient Node.js system, simply knowing that the event loop is ticking isn't enough to guarantee that your service should receive traffic. We use heartbeat monitoring to differentiate between two distinct states: Health and Readiness.
The Health Check (Liveness)
A health check answers a basic question: "Is the process currently running and responsive?" If this fails, the orchestrator (like Kubernetes) assumes the process is deadlocked or crashed and will restart the container.
For a Node.js server, a simple liveness probe might just return a 200 OK from a minimal route.
// Liveness: Is the process alive?
app.get('/healthz', (req, res) => {
res.status(200).send('OK');
});
The Readiness Check
A readiness check answers a more nuanced question: "Is this instance capable of serving traffic right now?" A process can be "alive" but still unable to process requests—for example, if it is currently establishing a connection to a database, warming up a cache, or waiting for a downstream dependency to settle.
If the readiness check fails, the orchestrator stops sending traffic to that instance, but it does not restart the process.
// Readiness: Is the process ready to accept traffic?
let isDatabaseConnected = false;
app.get('/ready', (req, res) => {
if (isDatabaseConnected) {
res.status(200).send('Ready');
} else {
// Tell the load balancer to route traffic elsewhere
res.status(503).send('Not Ready');
}
});
Why the distinction matters
If you conflate these two, you risk "flapping"—a scenario where a service that is just slow to initialize is repeatedly killed and restarted because it isn't "ready" fast enough. By separating them, you allow the system to remain in a pending state until it is truly operational. In a distributed system, this prevents cascading failures by ensuring that we only route requests to instances that have successfully finished their initialization, handled their disk constraints, and cleared their internal buffers.
Key Takeaway: Use Liveness checks to detect if a process needs a restart, and Readiness checks to control traffic flow based on whether the service is fully prepared to handle the workload.