How Do You Achieve Zero-Downtime Deployment?
Learn how zero-downtime deployment works using rolling updates, readiness probes, graceful draining, and backward-compatible migrations.
Expected Interview Answer
Zero-downtime deployment means releasing a new version of an application without any interruption or dropped requests for users, achieved by always keeping enough healthy instances of the old version serving traffic until new instances are verified healthy and gracefully draining connections before old instances are terminated.
The core mechanism is a rolling update: an orchestrator like Kubernetes starts new Pods running the new version, waits for each to pass a readiness probe confirming it can actually serve traffic, adds it to the load balancer’s pool, and only then removes an old Pod from that pool — never dropping below a minimum number of available instances. Terminating an old instance must be graceful: it stops receiving new requests immediately, but is given a grace period to finish in-flight requests before the process is killed, and a preStop hook can add a short delay to let the load balancer’s connection tracking catch up. Health checks are essential on both ends — a readiness probe prevents traffic from reaching a Pod before it is actually ready, and a liveness probe restarts Pods that hang mid-deployment. Beyond application-level rolling updates, zero downtime also requires database migrations to be backward-compatible during the transition window, since old and new code versions run simultaneously and both must be able to read and write against the same schema.
- Users experience no visible interruption during releases
- Enables frequent, low-risk deployments instead of risky maintenance windows
- Provides a built-in rollback path if new instances fail health checks
- Forces backward-compatible schema changes, improving overall reliability
AI Mentor Explanation
Zero-downtime deployment is like replacing tired fielders one at a time during a drinks break rather than pulling the entire fielding side off at once. A substitute only takes the field once the umpire confirms they are ready and positioned, and the outgoing fielder does not leave until their replacement is actually in place, so the team never fields fewer than eleven players. If a substitute is not ready in time, the original fielder simply stays on rather than leaving a gap. The match never pauses because the transition happens gradually, one player at a time, always keeping a full team on the field.
Step-by-Step Explanation
Step 1
Start new instances alongside old ones
The orchestrator launches new-version Pods without removing any old-version Pods yet.
Step 2
Gate on readiness probes
Each new Pod only joins the load balancer pool after its readiness probe confirms it can actually serve traffic.
Step 3
Drain and terminate old instances gradually
Remove an old Pod from the load balancer, let in-flight requests finish during a grace period, then terminate it.
Step 4
Repeat while keeping minimum availability
Continue the cycle Pod by Pod, never dropping below the configured minimum number of available instances.
What Interviewer Expects
- Understanding of rolling updates with readiness/liveness probes
- Awareness of graceful connection draining and preStop hooks
- Knowledge that database schema changes must stay backward-compatible during rollout
- Ability to explain minimum available / max surge tradeoffs
Common Mistakes
- Confusing zero-downtime deployment with simply restarting all instances at once
- Forgetting to configure readiness probes, causing traffic to hit unready Pods
- Making a breaking database schema change deployed at the same time as the code
- Not giving in-flight requests a grace period before killing the old instance
Best Answer (HR Friendly)
“Zero-downtime deployment means we can release new code without users ever noticing an interruption. We do this by starting new instances of the app alongside the old ones, waiting until the new ones are verified healthy, gradually shifting traffic over, and only then shutting down the old instances — so there is always a full set of working servers handling requests.”
Code Example
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
template:
spec:
containers:
- name: app
image: myapp:2.0
readinessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 3
lifecycle:
preStop:
exec:
command: ["sleep", "5"]
terminationGracePeriodSeconds: 30Follow-up Questions
- What is the difference between maxUnavailable and maxSurge in a rolling update?
- Why is a preStop hook needed alongside terminationGracePeriodSeconds?
- How do you keep a database migration backward-compatible during a rolling deploy?
- What is the difference between a readiness probe and a liveness probe?
MCQ Practice
1. What must happen before a new Pod receives production traffic in a rolling update?
A readiness probe confirms the Pod can actually serve requests before the orchestrator adds it to the load balancer pool.
2. Why is a grace period given before an old instance is fully terminated?
Graceful termination lets requests already being processed complete before the process is killed, avoiding dropped connections.
3. What must be true of a database schema change deployed alongside a rolling update?
During a rolling update, old and new versions of the app run at the same time, so both must work against the same schema.
Flash Cards
What is zero-downtime deployment? — Releasing a new version with no visible interruption to users.
What gates a new Pod joining the load balancer? — Passing its readiness probe.
What does a preStop hook do? — Adds a short delay before shutdown so load balancer connection tracking catches up.
Why must schema migrations be backward-compatible during rollout? — Old and new code versions run simultaneously against the same database.