// DevOps

Zero-Downtime Deployments: Blue-Green, Rolling and Canary Explained

How to ship new versions without taking your site offline: the main deployment strategies, how to handle database changes safely, and how to roll back in seconds.

Zero-Downtime Deployments: Blue-Green, Rolling and Canary Explained

There was a time when deploying meant a maintenance page and a late night. Today users expect your product to stay up while you change it. Zero-downtime deployment is how you do that, and it is mostly a matter of choosing a strategy and preparing your database for it.

Why deployments cause downtime

A naive deployment stops the old version, then starts the new one. In between, requests fail. Even if that gap is only a few seconds, it drops active sessions, breaks uploads and shows errors to anyone who happens to be using the product.

The fix is to never have a moment when no healthy version is serving traffic.

The three common strategies

Rolling deployment

Replace instances one at a time. While some run the old version, others run the new one, and the load balancer only sends traffic to healthy instances.

The point: never a moment with no healthy version.

  • Pros: needs no extra capacity beyond a spare instance or two.
  • Cons: during the rollout, two versions run side by side, so they must be compatible with each other. Rolling back means rolling forward again in reverse.

Blue-green deployment

Run two identical environments. "Blue" serves live traffic. You deploy the new version to "green", test it, and then switch the traffic over in one step.

sequenceDiagram
    participant U as Users
    participant L as Load balancer
    participant B as Blue v1
    participant G as Green v2

    U->>L: Send requests
    L->>B: Route traffic
    Note over G: Deploy version two
    G->>G: Run health checks
    G-->>L: Report healthy
    L->>G: Switch traffic
    U->>L: Send new requests
    L->>G: Route traffic
    Note over B: Keep for rollback
    L->>B: Rollback if needed
  • Pros: the switch is instant, and so is rolling back, because blue is still there untouched.
  • Cons: you pay for two environments during the release, and anything stateful, especially the database, still needs care.

Canary release

Send a small share of real traffic, say 5 percent, to the new version. Watch the error rate and latency. If the numbers hold, increase the share. If they do not, send everything back.

  • Pros: limits the damage of a bad release to a few users and gives you real evidence before you commit.
  • Cons: needs good monitoring and a router that can split traffic.

Which one to use

Situation Good fit
Small team, a few servers Rolling or blue-green
You need instant rollback Blue-green
High traffic, risky changes Canary
Kubernetes Rolling by default, canary with a service mesh or ingress rules

You do not need to adopt all three. Pick the simplest one that gives you a safe rollback.

The part that really bites: database changes

Application servers are easy to swap. The database is shared by both versions, so a change that breaks the old code will break it the moment you apply it. The standard answer is expand and contract:

Database changes are the hard part. Expand first, contract later.

  1. Expand. Make additive changes only: new columns that allow null, new tables. The old code ignores them.
  2. Migrate. Deploy the new code, which writes to both the old and new structure and reads from the new one. Backfill existing data.
  3. Contract. Once nothing uses the old structure, remove it in a later release.

Never rename or drop a column in the same release that stops using it. Split it across at least two deployments.

Health checks and readiness

A load balancer can only route around bad instances if it can tell they are bad. Give every service two endpoints:

  • A liveness check that says the process is running.
  • A readiness check that says it is ready for traffic, meaning it has connected to the database and warmed its caches.

Do not switch traffic until the readiness check passes. A simple Nginx example for switching between two upstreams:

upstream app_blue  { server 127.0.0.1:3001; }
upstream app_green { server 127.0.0.1:3002; }

# point this at the live colour, then reload
server {
    listen 443 ssl;
    location / { proxy_pass http://app_green; }
}

Running nginx -t && nginx -s reload applies the change without dropping existing connections.

Rolling back

Plan the rollback before the release, not during an incident:

A rollback you have never practised is only a hope.

  • Keep the previous version deployed and ready for as long as it is reasonable to need it.
  • Make configuration part of the release, so rolling back restores the matching settings.
  • Decide in advance which signal triggers a rollback, for example an error rate above a set value for five minutes.
  • Practise it. A rollback you have never tried is a hope, not a plan.

A release checklist

  1. Migrations are backward compatible with the version currently live.
  2. The new version passes its readiness checks before taking traffic.
  3. Dashboards and alerts for errors and latency are open.
  4. The rollback step is written down and takes one command.
  5. Someone is watching for the first ten minutes.

Conclusion

Zero downtime is not about expensive tooling. It is a habit: keep the old version alive until the new one proves itself, make database changes in small compatible steps, and make rollback boring. Start with whichever strategy your platform supports out of the box, and add canary releases when your traffic and monitoring justify them.

Filed underDeploymentDevOpsBlue-GreenCI/CD

Keep reading