"We'll deploy at 2am to avoid disrupting users" used to be standard advice. It's also an admission that the deployment process itself is risky. Zero-downtime deployment means you can ship at 2pm on a Tuesday and nobody notices — because the switch from old version to new version never leaves a gap where nothing is answering requests.
The core idea: never take the old version down first
The fundamental technique is simple to state: start the new version, confirm it's healthy, then route traffic to it, and only then stop the old version. If you stop the old version before the new one is ready, there's a window with no server answering — that's the downtime. Every zero-downtime strategy is a variation on this ordering.
Common strategies
- Rolling deployment — update instances one at a time behind a load balancer, so some instances always keep serving traffic.
- Blue-green deployment — run two identical environments; deploy to the idle one, verify it, then flip traffic over entirely, keeping the old one ready as an instant rollback.
- Canary release — send a small percentage of traffic to the new version first, watch for errors, then gradually increase it.
The part people forget: database migrations
Code deploys are the easy part. Database schema changes are where zero-downtime deployments actually go wrong, because for a brief period, both old and new code may be running against the same database. The safe pattern is to make migrations backward-compatible: add new columns without removing old ones immediately, deploy the code that uses them, and only clean up the old schema in a later, separate step once nothing depends on it anymore.
If a deployment plan doesn't explicitly account for "what happens to the database while both versions are briefly live," it isn't actually zero-downtime — it's zero-downtime until the first schema change.
Health checks make or break this
None of the above works without a reliable health check — an endpoint the load balancer or orchestrator can hit to confirm a new instance is actually ready to serve traffic, not just that the process has started. A service that reports healthy before its database connections are warmed up will happily receive real traffic and fail it.
What this looks like day to day
For most projects we run, this translates to: containerized deployments behind a platform that handles rolling updates automatically (Vercel, most managed container platforms), backward-compatible migrations as a standing rule rather than a special case, and a rollback plan that's actually been tested — not just assumed to work.

