The Soft Landing
The mark of production software isn't starting up — it's stopping without dropping anything.
What you're wiring up
Two drains, one principle. Backend drain: you want to deploy to b2, so you tell the balancer to stop sending it new work and let its current work finish. That needs a third state, draining, sitting between up and down — invisible to the picker, but its in-flight requests run to completion. When the in-flight count hits zero, it's out and safe to redeploy.
Balancer drain: on SIGTERM you stop accepting new connections, finish everything in flight, and exit 0. Bounded by a timeout, because a single stuck request must not hold shutdown hostage forever. If the timeout expires you force-close and exit nonzero — an honest signal that something didn't land cleanly.
This is why rolling deploys can show literally zero errors: every layer knows how to land softly. Order matters too — shut the traffic server down first and the admin server last, so /status stays readable while the machine is landing.
Assembly steps
hint
You already count in-flight per backend — drain is just a state plus watching that counter hit zero.
hint
Restore should put a backend back through the health-check thresholds, not straight into rotation on faith.
hint
signal.NotifyContext plus http.Server.Shutdown already means close listeners and wait for active requests.
hint
Your remaining job is the timeout context and the exit code — get both right.
Go deeper (after it passes)
The blueprint is complete — solid ink. Victory lap: put three real services behind it and roll a deploy with zero errors. Then read DDIA M5 (Replicate It) — zero-downtime rotation is the ops face of replica routing — and take Stage 3's you can only stop hearing from it into the Raft track.