A container process can be alive while the application is unable to serve traffic. Kubernetes health probes turn that distinction into scheduling behavior, but only when each probe answers one precise question.
Use readiness for traffic
Readiness should fail when the pod must stop receiving requests: a dependency is unavailable, migrations are running, or the application has not loaded its configuration. It should not restart the process.
The incident
A deployment looked healthy because every pod was Running, but users saw intermittent 502 responses. The application opened its port before database migrations finished, so the service sent traffic to pods that were alive and completely unready.
The first attempted fix increased the deployment delay. That reduced the frequency of the symptom but did not describe the application state. A fixed sleep is not a health model; it is a bet that the next deploy will be slower than the last one.
Use liveness for unrecoverable hangs
Liveness is for a process that is alive but cannot recover on its own. An aggressive liveness probe turns a slow dependency into a restart storm, so its timeout and failure threshold must reflect real startup and recovery behavior.
startupProbe:
httpGet:
path: /health/startup
port: http
failureThreshold: 30
periodSeconds: 5
readinessProbe:
httpGet:
path: /health/ready
port: http
periodSeconds: 5
livenessProbe:
httpGet:
path: /health/live
port: http
failureThreshold: 3
periodSeconds: 10Test probes during failure
Stop a dependency, delay startup, exhaust connections, and deploy a bad configuration in a test environment. The expected result is not merely a green pod: traffic should drain, restarts should be bounded, and rollout progress should remain observable.
The resolution
We split one overloaded health endpoint into startup, readiness, and liveness checks. Readiness verified dependencies needed to serve requests, startup allowed the application time to initialize, and liveness checked only for a process that had stopped making progress. Rollouts became slower by a few seconds and much safer.
We verified the change by killing the database connection, delaying the application boot, and forcing a bad configuration into staging. In each case, traffic stopped before the pod was restarted, and the rollout reported the real failure instead of presenting a green but useless status.
Keep the three decisions independent
A startup probe temporarily gates the other probes while initialization runs. Readiness decides whether this replica should receive new traffic; liveness should detect a process that is stuck and cannot recover. Keep liveness local and cheap rather than making every pod restart when a shared database has a bad afternoon. Also align terminationGracePeriodSeconds and any preStop work with the time the application needs to drain requests.
If all three probes answer the same question, the cluster has three sensors and one blind spot.
Probe design in one sentence
A health endpoint is an operational contract. Keep it cheap, deterministic, and explicit about what the platform should do next.