I separate liveness from readiness because they answer different questions. Liveness is “is the process alive enough to respond?” and should be cheap; readiness is “can this instance take traffic?” and can include dependency checks like DB connectivity or queue health. The common mistake is making readiness too expensive or flaky, which causes cascading restarts. I keep readiness fast by using short timeouts and a small set of essential checks (DB ping, migrations applied, critical config loaded). This snippet shows a simple approach: two endpoints, explicit status codes, and dependency checks behind a small interface so it’s testable. It’s boring, but it prevents a lot of noisy outages during deploys.