Health Checks Draining and Failure Capacity

Scaling DNS and Load Balancing · 40 min

System Design · Module 5 · Lesson 4 of 4 · 40 min

Health Checks Draining and Failure Capacity

Trace removal of an unhealthy server, distinguish readiness from liveness, and test whether surviving capacity can handle the peak.

Step through a backend removal →
Failure detection, safe request completion and sufficient surviving capacity are three different obligations.

01 The idea

The problem this lesson solves

For six equal-cost requests, round robin over A,B,C produces A,B,C,A,B,C. Each receives two.

Prerequisite: earlier lessons introduce the vocabulary and shared examples used here. Follow the module order.

ReadinessWhether an instance should receive new work now.
LivenessWhether a process is considered alive enough to keep running under the platform policy.
DrainingStopping new assignments while allowing existing work a bounded chance to finish.

02 Worked example

Follow one worked example

Health Checks Draining and Failure Capacity worked diagram01FailureB stops responding02Probe windowSome calls still selectB03RemovalOnly A and C eligible04RecoveryCapacity + retry policyRead events in time order, from left to right.Health Checks Draining and Failure Capacity compact diagram01FailureB stops responding02Probe windowSome calls still select B03RemovalOnly A and C eligible04RecoveryCapacity + retry policy
Failure: B stops responding • Probe window: Some calls still select B • Removal: Only A and C eligible • Recovery: Capacity + retry policy.

Trace the example in order. Follow the same identities, units and state transitions through the diagram and the events below.

1
All healthyFor six equal-cost requests, round robin over A,B,C produces A,B,C,A,B,C. Each receives two.
2
Observe a failureAfter request 2, health checking marks B unavailable. The simulation removes B before request 3 and preserves the next eligible position, C.
3
Continue routingThe sequence becomes A,B,C,A,C,A. Requests 3 through 6 never select B, but request 2 is not magically recovered.
4
Check remaining capacityA and C must handle the new total. If each was already saturated, removing B still leaves an overloaded system.

Failure detection, safe request completion and sufficient surviving capacity are three different obligations.

03 The method

Mechanisms decisions and a guided tutorial

Work through the explanation in order, then apply it in the tutorial. Each comparison names a cost as well as a benefit.

Choice or conceptPurposeBoundary or cost
Readiness removalStops new assignmentsDetection and propagation take time
DrainingLets in-flight work finishNeeds a deadline and stream policy
Safe retryRecovers an eligible requestRequires operation semantics
Failure headroomHandles load after removalHealth checks do not add capacity

Health checks have a detection window

A readiness probe determines whether an instance should receive new requests; liveness asks whether a process should be restarted. These are distinct decisions. With checks every five seconds and two consecutive failures required, detection is roughly one to two check intervals plus probe timeout and scheduling effects, depending on when the failure occurs. Do not promise immediate removal. A process can pass a shallow probe while real requests fail, but making every instance fail readiness whenever a shared dependency blips can also turn partial degradation into a total outage.

Removal does not replay an in-flight write safely

If a backend fails after committing a write but before responding, the balancer cannot infer whether the operation happened. Retry only when the operation's semantics and body replayability permit it; the idempotency contract from the API lesson matters here. During planned deployments, stop assigning new requests, drain existing work for a bounded time, and terminate only afterward. Long-lived streams need an explicit drain and reconnect policy.

Budget for the failure domain

Three instances at 100 budgeted requests/s each serve 300 QPS in normal operation. After losing one, they serve only 200 QPS. If the peak is 240 QPS, a green health-check system cannot prevent overload. Place redundant entry points and instances across the failure domains you promise to tolerate, then test the surviving capacity of the cache and database as well. Redundancy without a recovery test is only a diagram.

A probe has a timeline

If checks run every five seconds and require two failures, a real backend can continue receiving selections while detection proceeds. Probe timeout, scheduling and the moment of failure affect the removal time. A green shallow probe can also miss an application-path failure.

Avoid the opposite extreme of making every instance unready during any shared database blip. Removing all app capacity together can prolong an outage. Define local readiness, shared dependency degradation and process restart behavior separately, and test a shared-failure scenario.

Draining addresses planned termination

A rollout should stop new routing to an instance, wait for propagation, allow in-flight work up to a deadline, then terminate it. Long-lived streams need a reconnect policy. Existing writes can finish even when their clients lose the response.

A proxy must not blindly replay every POST after a connection closes. The backend may have committed it. The idempotency contract and request-body replayability determine whether a retry is safe. Health checking does not resolve that unknown outcome.

Health is not spare capacity

Three instances budgeted at 100 QPS each supply 300 QPS normally. Losing one leaves 200. A target of 240 QPS therefore exceeds surviving capacity even after the balancer perfectly removes the dead backend.

Count the failure domain you promise to tolerate. Losing a zone can remove multiple instances, a cache node and a network route at once. Test the combined remaining system rather than validating only the balancer’s list of healthy targets. Define admission or degraded behavior when demand exceeds the tested budget.

Guided tutorial

1. Inspect DNS

Run dig example.com A if dig is available. Find the answer's TTL and address. Repeat and explain why a cached answer might have a different remaining TTL. Record observations rather than assuming a fixed IP.

2. Trace the pool

Run both interactive presets. Record the selected backend for each request. Confirm the failed backend receives no new selection after its removal.

3. Write a readiness contract

List which local checks must pass to accept a redirect request. Separate a local initialization failure from a shared database slowdown and specify degraded behavior for the latter.

4. Rehearse a rollout

Write the sequence: mark one instance unready, wait for routing propagation, drain in-flight work within a deadline, replace it, warm it, then return it to the pool. State how many instances remain and whether they can serve the peak.

# Observational commands; responses vary over time
dig example.com A
curl -I https://example.com

# Simplified routing policy, not a full proxy configuration
eligible = instances whose readiness is healthy
backend = next_round_robin(eligible)
forward request using a bounded upstream deadline

05 Cheat sheet

Review the decisions

Use this table to explain the mechanism and its limit without memorizing a product name.

Choice or conceptRememberCheck
Readiness removalStops new assignmentsDetection and propagation take time
DrainingLets in-flight work finishNeeds a deadline and stream policy
Safe retryRecovers an eligible requestRequires operation semantics
Failure headroomHandles load after removalHealth checks do not add capacity
ReadinessWhether an instance should receive new work now.
LivenessWhether a process is considered alive enough to keep running under the platform policy.
DrainingStopping new assignments while allowing existing work a bounded chance to finish.

06 Where & why

Check the primary references

Use official references for protocol and implementation details. The questions here are teaching prompts.

Primary reference
NGINX HTTP load balancing

Read NGINX HTTP load balancing

Primary reference
DNS concepts

Read DNS concepts

Primary reference
Google SRE cascading failures

Read Google SRE cascading failures

State the implementation version and the workload assumptions when defending your own design.

07 Interview questions

Explain the reasoning out loud

Answer before opening the explanation. The questions progress from vocabulary to decisions and failure behavior.

What does Readiness mean?
Whether an instance should receive new work now.
What does Liveness mean?
Whether a process is considered alive enough to keep running under the platform policy.
What does Draining mean?
Stopping new assignments while allowing existing work a bounded chance to finish.
Why distinguish readiness from liveness?
An instance can be alive but not ready for new work. Restarting every alive process during a shared slowdown can worsen recovery.
Does removing a target recover its in-flight request?
No. The existing operation may fail or have an unknown outcome. Retry and recovery follow the operation’s contract.
Why can a green probe coexist with user errors?
The probe may not exercise the failing request path. Probe depth and thresholds need a deliberate trade-off.
What should happen before terminating a healthy old instance?
Stop new assignments, allow routing state to propagate and drain existing work within a bounded deadline.
What must be measured during failure testing?
Successful throughput, tail latency, retries, dependency saturation and surviving capacity, not only the healthy-target count.

08 Practice problems

Practice a new case

Solve the new cases before revealing hints. Complete worked solutions follow the set.

Readiness decision

Easy
A process is running but has not loaded its required local configuration; should it receive new requests?
Follow-up
State the assumption or edge case that makes the answer correct.
Show the hint
Alive and ready are separate.

In-flight work

Easy
A target leaves the healthy pool while a POST is in flight; does removal prove the write failed?
Follow-up
State the assumption or edge case that makes the answer correct.
Show the hint
Routing eligibility does not reveal commit state.

Failure capacity

Medium
Check whether four instances budgeted at 80 QPS each can serve 260 QPS after one fails.
Follow-up
Healthy routing is not extra capacity.
Show the hint
Count only survivors.

Drain timeout

Medium
A stream lasts longer than the rollout drain deadline; specify a client-visible policy.
Follow-up
State the assumption or edge case that makes the answer correct.
Show the hint
A finite drain cannot wait forever.

Shared probe failure

Medium
Every app target becomes unready during a 10-second database slowdown; explain the amplification risk.
Follow-up
State the assumption or edge case that makes the answer correct.
Show the hint
The dependency is shared.

Deployment incident

Hard
Explain a spike in duplicate creations during rolling deploys and propose a fix across the proxy and API.
Follow-up
Old instances are terminated while some requests are in flight.
Show the hint
Join draining with the timeout ambiguity from the API lesson.

Worked solutions

1. Readiness decision

It should remain unready until the required initialization succeeds, under the documented deployment policy.

2. In-flight work

No. The operation may have committed or failed. Use its retry/recovery contract rather than infer the outcome from target removal.

3. Failure capacity

Three survivors provide 240 QPS, below 260. At least five such instances are needed to retain four survivors and 320 QPS after one failure under this model.

4. Drain timeout

Define a reconnect/resume mechanism or documented termination behavior at the deadline. Coordinate retries and state recovery instead of assuming every stream finishes.

5. Shared probe failure

All frontends may disappear simultaneously and need time to recover readiness. Design degraded behavior and thresholds so a shared transient failure does not automatically remove every useful serving path.

6. Deployment incident

An old instance may commit before losing its response; an automatic retry creates another object. Drain existing work, bound retry behavior, and implement durable scoped idempotency keys in the API. Monitor retries and duplicate-key hits to verify the change.