Category: Cloud & Infrastructure Tags: rolling-deployment kubernetes zero-downtime-deployment

What Is Rolling Deployment?

By Oleksandr Andrushchenko — Published on — Modified on
0 Likes
0 Dislikes

Rolling deployment is a software release strategy that updates an application incrementally instead of replacing every running instance at once. The deployment controller starts new instances, waits for them to become ready, and removes old instances in batches until the entire application runs the new version. Rolling deployments are widely used in Kubernetes, Amazon ECS, and other platforms that manage replicated services.

What Is Rolling Deployment? Kubernetes Rolling Updates, maxSurge, maxUnavailable, Zero-Downtime Releases, and Rollback
What Is Rolling Deployment? Kubernetes Rolling Updates, maxSurge, maxUnavailable, Zero-Downtime Releases, and Rollback

The main advantage is the ability to release software without taking the entire service offline or maintaining a completely separate production environment. However, rolling deployment does not automatically guarantee zero downtime or safe rollback. Readiness checks, capacity limits, graceful shutdown, database compatibility, and traffic routing all determine whether users experience interruptions during a release.

Table of Contents

How Rolling Deployment Works

Consider an API running six instances of version v1. A new version, v2, contains a performance improvement and a new response field. Replacing all six instances simultaneously would temporarily remove the service's entire serving capacity unless replacement instances were already available.

With rolling deployment, the platform replaces instances gradually. Both versions temporarily serve production requests, and the old version is removed only as the new version becomes available.

Rolling Update Lifecycle

A typical deployment proceeds through the following stages:

  1. Start: Six instances run v1 and serve production traffic.
  2. Create: The controller starts one or more v2 instances.
  3. Verify: New instances must pass readiness checks before receiving traffic.
  4. Replace: The controller removes selected v1 instances from service.
  5. Repeat: Additional v2 instances replace the remaining v1 instances.
  6. Complete: All desired instances run v2.

The number of instances created or removed simultaneously depends on deployment configuration and available infrastructure capacity.

For example, a Kubernetes deployment can temporarily run more than six instances during an update. This extra capacity allows the controller to start replacement pods before terminating old ones.

Example: Replacing Six Instances

Assume the platform allows two additional instances during deployment and requires all six desired instances to remain available.

Stage Old Version New Version Total Instances
Before deployment 6 0 6
Start first batch 6 2 8
First batch ready 4 2 6
Start second batch 4 4 8
Second batch ready 2 4 6
Final replacement 0 6 6

This is a simplified illustration of a healthy rollout. In a real cluster, terminating pods may remain visible while they finish existing requests, and the controller may create or remove pods asynchronously.

The important property is that replacement capacity becomes available before too much existing capacity disappears.

What Rolling Deployment Does Not Guarantee

Rolling deployment limits how quickly instances are replaced, but it does not automatically validate application correctness.

A new version can pass readiness checks while returning incorrect data, increasing database load, or failing only for certain customer requests.

It is possible to complete a technically successful rolling update that introduces a serious production regression. Deployment health and application health must therefore be monitored separately.

Rolling vs. Canary and Blue-Green Deployment

Rolling, canary, and blue-green deployments all reduce the disruption associated with software releases, but they differ in how they manage instances and production exposure.

The distinction matters because a gradual replacement of instances is not necessarily a controlled experiment with a new application version.

Strategy Release Mechanism Capacity Requirements Rollback Characteristics
Rolling Replace instances in batches Usually modest temporary capacity Replace updated instances with the old version
Canary Control exposure to the new version Capacity for stable and canary traffic Route traffic away from the canary
Blue-green Switch between separate environments Often requires substantial duplicate capacity Switch back while old environment remains intact

Rolling vs. Canary Deployment

In a rolling deployment, the controller replaces instances according to availability and surge limits. As more new instances become ready, they typically receive an increasing share of production traffic.

However, the controller does not necessarily control an exact request percentage or require statistical evidence before advancing.

A canary deployment deliberately exposes the new version to a limited traffic segment, evaluates its behavior, and increases exposure only when defined release conditions pass.

Canary Deployment
Canary Deployment

For example, a canary might stay at 5% traffic for 15 minutes while the deployment system compares error rates and latency. A standard rolling deployment may continue replacing instances as soon as they become ready.

Rolling vs. Blue-Green Deployment

Blue-green deployment keeps the old and new environments separate. Once the new environment is ready, the routing layer switches traffic between them.

Blue-Green Deployment
Blue-Green Deployment

Rolling deployment replaces instances within the active service over time, so old and new versions coexist throughout the update.

Blue-green can provide a fast traffic rollback if the previous environment is preserved. Rolling rollback usually requires another instance replacement process, which takes time.

For related approaches, see What Is Blue-Green Deployment? and Traffic Routing Strategies for Zero-Downtime Deployments.

Rolling Deployment Configuration

Kubernetes provides a built-in rolling update strategy for Deployments. Two settings are especially important: maxSurge and maxUnavailable.

They determine how much temporary capacity can be added and how much desired capacity can be unavailable during a rollout.

maxSurge: Extra Capacity During Deployment

maxSurge specifies how many additional pods the controller may create above the desired replica count.

For a Deployment with six replicas and maxSurge: 2, the controller may temporarily create up to eight non-terminating pods during an update.

Setting maxSurge to a percentage is also supported. Kubernetes rounds percentage-based surge values up.

Extra capacity improves availability but requires sufficient CPU, memory, IP addresses, and scheduling capacity in the cluster.

maxUnavailable: Allowed Capacity Reduction

maxUnavailable specifies how many desired replicas may be unavailable during an update.

For six replicas and maxUnavailable: 1, the controller may proceed while at least five desired replicas remain available.

Setting maxUnavailable: 0 instructs the controller not to intentionally reduce available replicas below the desired count during a healthy rollout.

This does not guarantee continuous application availability during infrastructure failures, and it does not mean that existing connections can never be interrupted.

Choosing the Right Configuration

The following configurations illustrate different trade-offs:

# Availability-focused
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 2
    maxUnavailable: 0

# Capacity-constrained
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 0
    maxUnavailable: 1

# Faster replacement
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 50%
    maxUnavailable: 25%

With maxSurge: 0, the controller must free capacity before creating replacements. This can reduce infrastructure requirements but temporarily lowers available capacity.

Higher surge values can accelerate deployments, but they may increase load on shared databases, caches, and other dependencies as new instances initialize.

Both values cannot be zero simultaneously because the controller would have no permitted way to progress.

Requirements for Zero-Downtime Releases

A rolling deployment can maintain the desired number of ready instances while still interrupting requests. Availability depends on how applications start, become ready, and shut down.

Zero-downtime behavior requires coordination between the deployment controller, service routing, and application lifecycle.

Readiness and Startup Checks

A new instance should not receive traffic until it can serve real requests successfully.

For example, a FastAPI service may need to initialize database connections, load configuration, or warm application caches before becoming ready.

A simple readiness endpoint might look like this:

from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI()

ready = False


@app.on_event("startup")
async def startup():
    global ready

    # Initialize required application resources.
    ready = True


@app.get("/ready")
async def readiness():
    if not ready:
        return JSONResponse(
            {"status": "not_ready"},
            status_code=503,
        )

    return {"status": "ready"}

This simplified example demonstrates the readiness contract. For new FastAPI applications, lifespan handlers are generally preferable to the older startup-event interface.

Production readiness should reflect whether the instance can serve requests, without making it unnecessarily dependent on every optional downstream service.

See Health Checks, Readiness, and Liveness Probes for the distinction between startup, readiness, and liveness checks.

Graceful Shutdown and Connection Draining

When an old pod is terminated, Kubernetes begins its shutdown process and updates endpoint availability. Existing requests may still be in progress while routing changes propagate.

Applications should handle SIGTERM, stop accepting new work when appropriate, and allow in-flight requests to complete within the configured termination grace period.

For long-running requests, WebSockets, or streaming responses, the application may need explicit connection-draining behavior.

Increasing terminationGracePeriodSeconds without implementing graceful shutdown is not sufficient. The application server must actually wait for active work or close connections deliberately.

Database Schema Compatibility

During a rolling update, both versions run simultaneously against the same database.

Suppose version v2 renames a database column and immediately drops the original. Existing v1 instances may fail because they still query the old column.

Use an expand-and-contract migration instead:

  1. Add the new column or schema structure without removing the old one.
  2. Deploy application code that supports both representations where necessary.
  3. Backfill or migrate existing data.
  4. Switch reads and writes to the new representation.
  5. Remove the old schema only after all dependent versions are retired.

The same compatibility principle applies to message formats, cache keys, shared sessions, and API contracts.

Production Design Example

Consider a Python API running on Kubernetes with 12 replicas across three availability zones. The service receives 2,400 requests per second and must remain available during application releases.

The application uses PostgreSQL and Redis, and each pod normally handles approximately 200 requests per second under balanced traffic.

Capacity Planning During the Rollout

The deployment uses maxSurge: 3 and maxUnavailable: 0. Kubernetes may create up to three additional non-terminating pods during the rollout while maintaining the desired availability target.

This requires sufficient cluster capacity for up to 15 pods during normal rollout progression.

However, application initialization also creates temporary resource spikes. New pods may open database connections, populate local caches, and register with external services simultaneously.

If each pod opens a PostgreSQL pool of 20 connections, 15 pods can potentially consume 300 database connections before accounting for workers, administration, and other services.

Capacity planning must include these shared dependencies rather than focusing only on pod CPU and memory.

Production Release Process

The release pipeline performs these steps:

  1. Build a container image and publish it using an immutable image digest.
  2. Run unit, integration, and compatibility tests.
  3. Apply backward-compatible database migrations.
  4. Update the Kubernetes Deployment image.
  5. Wait for the new pods to pass startup and readiness checks.
  6. Monitor rollout progress, error rates, latency, and dependency saturation.
  7. Mark the release successful only after the rollout and post-deployment checks pass.

The deployment pipeline should distinguish a successful Kubernetes rollout from a successful business release.

For example, all pods may become ready while the new version introduces a slower SQL query. A post-deployment performance check can detect the regression even though the Deployment reports success.

Failure Scenario: New Pods Never Become Ready

Suppose the new version requires an environment variable that is missing from production configuration.

The container starts but fails initialization, so its readiness probe never succeeds. With maxUnavailable: 0, the controller generally preserves available old-version capacity rather than intentionally removing it to continue the rollout.

The rollout stalls and eventually exceeds its progress deadline. Kubernetes reports the failure, but it does not automatically restore the previous Deployment revision simply because the progress deadline was exceeded.

The deployment pipeline must explicitly decide whether to roll back, notify an operator, or wait for remediation.

For broader operational guidance, see Kubernetes Best Practices for Production.

Ready-to-Use Example

The following example creates a Kubernetes Deployment with four replicas, readiness and liveness probes, resource limits, and a rolling update strategy. It then demonstrates updating the application image, observing rollout progress, and reverting to the previous revision.

The example uses NGINX as a lightweight HTTP application so that the deployment mechanics can be tested without building a custom container image.

Kubernetes Deployment Manifest

Save the following as deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rolling-demo
  labels:
    app: rolling-demo
spec:
  replicas: 4
  revisionHistoryLimit: 5
  progressDeadlineSeconds: 180

  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

  selector:
    matchLabels:
      app: rolling-demo

  template:
    metadata:
      labels:
        app: rolling-demo

    spec:
      terminationGracePeriodSeconds: 30

      containers:
        - name: nginx
          image: nginx:1.26.3-alpine

          ports:
            - containerPort: 80

          startupProbe:
            httpGet:
              path: /
              port: 80
            periodSeconds: 2
            failureThreshold: 15

          readinessProbe:
            httpGet:
              path: /
              port: 80
            periodSeconds: 5
            failureThreshold: 2

          livenessProbe:
            httpGet:
              path: /
              port: 80
            periodSeconds: 10
            failureThreshold: 3

          resources:
            requests:
              cpu: 50m
              memory: 64Mi
            limits:
              cpu: 250m
              memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
  name: rolling-demo
spec:
  selector:
    app: rolling-demo

  ports:
    - port: 80
      targetPort: 80

  type: ClusterIP

The Deployment starts four replicas and allows one additional pod during an update. It requires all four desired replicas to remain available during a healthy rollout.

The startup probe gives the application time to initialize before liveness and readiness checks take effect. The readiness probe controls whether a pod is eligible for Service traffic.

The example uses a simple HTTP endpoint. Real services should use dedicated readiness checks that reflect their actual ability to handle requests.

Deploy and Inspect the Application

Apply the manifest and wait for the initial deployment:

kubectl apply -f deployment.yaml

kubectl rollout status deployment/rolling-demo

kubectl get pods -l app=rolling-demo -o wide

Inspect the rollout configuration:

kubectl describe deployment rolling-demo

You should see four desired replicas, with all pods eventually becoming ready.

To access the service locally, use port forwarding:

kubectl port-forward service/rolling-demo 8080:80

Then verify the response from another terminal:

curl -i http://127.0.0.1:8080/

Perform a Rolling Update

Update the container image to another published NGINX version:

kubectl set image deployment/rolling-demo \
  nginx=nginx:1.27.5-alpine

Watch the rollout progress:

kubectl rollout status deployment/rolling-demo

kubectl get pods -l app=rolling-demo --watch

During the update, Kubernetes creates new pods and removes old pods according to the configured surge and availability limits.

With four replicas and maxSurge: 1, the controller normally creates one replacement pod at a time before reducing old-version capacity.

New pods must become ready before the controller can safely continue replacing the remaining old pods.

Inspect Deployment Revisions

Kubernetes records Deployment revisions through ReplicaSets.

View rollout history:

kubectl rollout history deployment/rolling-demo

Inspect the ReplicaSets created during the update:

kubectl get replicasets -l app=rolling-demo

Older ReplicaSets may remain with zero replicas so the controller can restore previous pod templates when requested.

The revisionHistoryLimit setting controls how many old ReplicaSets are retained for rollback.

Simulate a Failed Deployment

To observe failure behavior, update the Deployment to a deliberately nonexistent image tag:

kubectl set image deployment/rolling-demo \
  nginx=nginx:does-not-exist

Inspect the resulting pod states:

kubectl get pods -l app=rolling-demo

kubectl describe deployment rolling-demo

The new pod should fail to pull its image and remain unavailable. Because maxUnavailable is zero, the controller should preserve available old-version capacity during the stalled rollout.

After the configured progress deadline, the Deployment can report a ProgressDeadlineExceeded condition.

The controller does not automatically roll back solely because this condition is reported.

Roll Back to the Previous Version

Restore the previous Deployment revision:

kubectl rollout undo deployment/rolling-demo

kubectl rollout status deployment/rolling-demo

Verify that the pods are healthy:

kubectl get deployment rolling-demo

kubectl get pods -l app=rolling-demo

The rollback changes the desired pod template to the previous revision. Kubernetes then performs another rollout to reconcile the running pods.

Rollback is not an instantaneous switch. The time required depends on image availability, pod startup, readiness checks, and infrastructure capacity.

When finished, remove the demonstration resources:

kubectl delete -f deployment.yaml

Monitoring and Rollback

Kubernetes reports whether a Deployment has reached its desired state, but operational monitoring must also determine whether the new version behaves correctly under production traffic.

A successful rollout should satisfy both infrastructure health and application-level release criteria.

Metrics to Monitor

Important metrics include:

  • Availability: Ready replicas compared with desired replicas
  • Errors: HTTP 5xx responses, exceptions, and failed operations
  • Latency: P50, P95, and P99 request duration
  • Resources: CPU, memory, connection pools, and queue depth
  • Restarts: Container crashes, OOM kills, and restart counts
  • Dependencies: Database latency, cache errors, and downstream timeouts

Application metrics should include a version or deployment label. Without version-specific measurements, a regression affecting only newly deployed instances may be hidden in aggregate metrics.

For practical monitoring principles, see Metrics That Actually Matter.

Automated Rollback in CI/CD

A deployment pipeline can wait for rollout completion and trigger rollback when the command fails.

#!/usr/bin/env bash
set -euo pipefail

DEPLOYMENT="rolling-demo"
NAMESPACE="default"

if ! kubectl rollout status \
    deployment/"$DEPLOYMENT" \
    -n "$NAMESPACE" \
    --timeout=180s; then

    echo "Rollout failed; restoring previous revision"

    kubectl rollout undo \
        deployment/"$DEPLOYMENT" \
        -n "$NAMESPACE"

    kubectl rollout status \
        deployment/"$DEPLOYMENT" \
        -n "$NAMESPACE" \
        --timeout=180s

    exit 1
fi

echo "Rollout completed successfully"

This script handles failures reported by the Kubernetes rollout command. It does not detect business regressions after all pods become ready.

Production pipelines should combine rollout status with metrics-based release gates and post-deployment tests.

Also, an automatic rollback can conflict with GitOps controllers if the desired image in Git still points to the failed version. The deployment system must update or reconcile the authoritative desired state rather than repeatedly fighting the controller.

Common Mistakes

Rolling deployment is easy to configure, but several operational mistakes can still cause downtime or failed releases.

Using Liveness Instead of Readiness

A liveness probe determines whether a container should be restarted. It does not indicate that the application is ready to receive production requests.

Use a separate readiness probe and ensure it succeeds only when the instance can serve traffic.

Insufficient Capacity for Surge Pods

With maxSurge greater than zero, the cluster must have resources available for additional pods.

If no node has enough CPU or memory, replacement pods may remain Pending and the rollout can stall.

Breaking Database Compatibility

Old and new versions coexist during the rollout. Removing database fields or changing shared message formats without compatibility planning can break old instances.

Use expand-and-contract migrations and maintain compatibility throughout the deployment window.

Terminating Pods Before Requests Finish

Removing a pod from Service endpoints does not necessarily mean every existing request has completed.

Configure graceful shutdown, connection draining, and an appropriate termination grace period.

Assuming Kubernetes Automatically Rolls Back

Kubernetes can report a failed rollout without automatically restoring the previous revision.

Configure rollback behavior in the deployment pipeline or progressive-delivery controller, and test it before relying on it during an incident.

Production Checklist

Before enabling rolling deployments for a production service, verify that the application can safely operate with mixed versions and that the infrastructure can maintain sufficient capacity.

  • Strategy: Configure appropriate maxSurge and maxUnavailable values.
  • Capacity: Reserve CPU, memory, network, and dependency capacity for temporary additional instances.
  • Readiness: Prevent traffic from reaching instances before initialization completes.
  • Shutdown: Handle termination signals and allow in-flight requests to finish.
  • Compatibility: Support mixed application versions and backward-compatible database changes.
  • Monitoring: Track rollout status, errors, latency, and version-specific performance.
  • Rollback: Test restoration of previous revisions and coordinate it with CI/CD or GitOps.
  • Images: Use immutable image references to make releases reproducible.
  • Validation: Require post-deployment checks before marking the release successful.

Frequently Asked Questions

Rolling deployments are widely supported by container orchestration platforms, but their behavior depends on application readiness, resource limits, and the deployment controller.

Does Rolling Deployment Guarantee Zero Downtime?

No. Rolling deployment can maintain serving capacity during an update, but downtime is still possible if readiness checks are incorrect, capacity is insufficient, or connections are terminated abruptly.

Zero-downtime releases require coordinated application lifecycle management and backward-compatible changes.

What Is the Difference Between Rolling and Canary Deployment?

Rolling deployment replaces application instances in batches. Canary deployment controls how much production traffic reaches the new version and usually includes explicit analysis before promotion.

A rolling update can be combined with canary analysis, but they are not the same strategy.

How Fast Can a Rolling Deployment Be Rolled Back?

Rollback requires the platform to reconcile running instances with a previous application version. The duration depends on image downloads, scheduling, startup time, readiness checks, and the number of replicas.

It is generally not an instantaneous traffic switch like a blue-green rollback can be.

Is Rolling Deployment the Default in Kubernetes?

Yes. Kubernetes Deployments use the RollingUpdate strategy by default.

The default maxSurge and maxUnavailable values are both 25%, with percentage rounding handled according to their respective rules.

Does Amazon ECS Support Rolling Deployments?

Yes. Amazon ECS supports rolling deployments for services. Deployment configuration can control the minimum healthy capacity and maximum running task count during replacement.

For more information, see Amazon ECS Deployment Strategies and Auto Scaling.

Conclusion

Rolling deployment updates applications incrementally by replacing old instances with new ones while maintaining service capacity. It is a practical default for replicated stateless services because it avoids replacing every instance simultaneously and usually requires less temporary infrastructure than a full blue-green environment.

Its reliability depends on the details: readiness probes, surge capacity, graceful shutdown, database compatibility, monitoring, and rollback automation. A successful instance replacement is not necessarily a successful software release.

Key Takeaway: Rolling deployment reduces release disruption by updating instances in controlled batches. Use it with reliable readiness checks, sufficient spare capacity, backward-compatible changes, and automated monitoring to achieve predictable production releases.

These related articles explain deployment strategies, Kubernetes lifecycle management, and production availability.

Comments (0)