Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
A 'health check' sounds simple until you have a load balancer that kills your app whenever Redis blips. The trick: two endpoints. /healthz answers 'is the process alive?' — always 200 unless the process is broken. /readyz answers 'can this instance serve traffic right now?' — 503 if a downstream the request will need is down. Load balancers route on /readyz. Process supervisors kill on /healthz. Conflate them and your LB will yank a perfectly fine app out of rotation every time S3 has a hiccup, OR your supervisor will never restart a wedged process. Kubernetes formalized this distinction; the rest of us should adopt it.
The right shape: /healthz is a one-liner returning 200 (or 503 only if the process has detected itself as broken). /readyz checks every dependency this instance's traffic depends on — DB, cache, maybe one critical upstream — with short timeouts (50-200ms) and returns 503 if any are down. Then your LB polls /readyz and your supervisor / orchestrator polls /healthz. Two endpoints, two semantics, no overlap.
/healthz should always be 200 (or you have a problem); /readyz should be 200 with all dependencies up./readyz — you should get 503 with a clear JSON saying which dep failed. Restart it; back to 200./readyz (NOT /healthz) for traffic routing. Configure your process supervisor (or k8s livenessProbe) to poll /healthz for restarts./readyz timeout of 200ms. Make the DB check sleep 500ms. Confirm /readyz returns 503 due to the timeout, not the DB itself — and that you can tell the difference from the response body.package main
import (
"context"
"database/sql"
"encoding/json"
"net/http"
"time"
)
var db *sql.DB
var redisOK func(context.Context) error
// /healthz — process liveness. Always 200 unless the process itself is broken.
func healthz(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
_, _ = w.Write([]byte("ok"))
}
// /readyz — can this instance serve a real user request right now?
func readyz(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 200*time.Millisecond)
defer cancel()
status := map[string]string{}
code := 200
if err := db.PingContext(ctx); err != nil {
status["db"] = "fail: " + err.Error()
code = 503
} else {
status["db"] = "ok"
}
if err := redisOK(ctx); err != nil {
status["redis"] = "fail: " + err.Error()
code = 503
} else {
status["redis"] = "ok"
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
_ = json.NewEncoder(w).Encode(status)
}go run main.go