Concept · Web services

Liveness and readiness checks

One probe asks “should I restart you?”, the other “should I send you traffic?” — mixing them up causes outages.

3 minhealth checklivenessProbereadinessProbe/healthz

Orchestrators and load balancers keep asking your service whether it's healthy. Kubernetes asks two different questions, and they need different answers.

ProbeQuestionOn failure
LivenessIs this process stuck beyond repair?The container is restarted
ReadinessCan this instance handle a request right now?It's removed from the Service's endpoints; no restart
StartupHas it finished booting?Liveness and readiness wait until it passes
yaml
livenessProbe:
  httpGet: { path: /livez, port: 8080 }
  periodSeconds: 10
  failureThreshold: 3
readinessProbe:
  httpGet: { path: /readyz, port: 8080 }
  periodSeconds: 5

What each endpoint should check

Liveness: almost nothing. Return 200 if the process can serve HTTP at all. Never check the database here. If the database goes down, every pod fails liveness, every pod restarts, and a database outage becomes a restart loop across the whole fleet that still can't fix the database.

Readiness: what this instance needs to do useful work. Has it loaded its config and warmed its caches? Can it reach the dependencies it can't work without? Is it shutting down? Fail readiness during graceful shutdown so traffic drains away before the process exits.

go
mux.HandleFunc("GET /livez", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })
mux.HandleFunc("GET /readyz", func(w http.ResponseWriter, r *http.Request) {
	if shuttingDown.Load() || !warm.Load() {
		http.Error(w, "not ready", http.StatusServiceUnavailable)
		return
	}
	w.WriteHeader(http.StatusOK)
})

Pitfalls

  • Shared dependencies in readiness. If every pod checks the same database and it blips, every pod goes unready at once and the service serves nothing, not even cached or degraded responses. Check only what's specific to the instance, or use a slower threshold for shared dependencies.
  • Probes that do real work (run a query, call another service) add load and can time out under exactly the pressure you're trying to detect. Keep them cheap.
  • Timeouts shorter than a GC pause or cold start cause restarts that look random. Use a startup probe for slow boots.

Load balancers outside Kubernetes run the same readiness-style check to decide whether to send traffic to a target. See API gateway vs load balancer. Health checks are also the signal that rolling and canary deploys use to decide whether to continue.

Learn it in depth