Pavan Rangani

HomeBlogRolling, Blue-Green, Canary: Which Deploy Strategy Fits

Rolling, Blue-Green, Canary: Which Deploy Strategy Fits

By Pavan Rangani · August 18, 2026 · DevOps & Cloud

Rolling, Blue-Green, Canary: Which Deploy Strategy Fits

Three deployment strategies get named in every architecture discussion — rolling, blue-green, and canary — usually as if canary is the sophisticated destination and the others are training wheels. That framing is wrong. Deployment strategies are a genuine trade between infrastructure cost, blast radius when a release is bad, and how fast you can undo it. The right one depends on your constraints, not your seniority.

Rolling: the default, and why it is fine

A rolling deployment replaces old instances with new ones a few at a time. Kubernetes does this out of the box: it starts some new pods, waits for them to pass readiness, terminates some old ones, and repeats until the fleet is new. At no point is the whole service down, and you never need double the capacity.

The cost is real but usually acceptable: for a while, both versions serve traffic at once. Your code has to tolerate that — the new version cannot assume a database column the old version does not write, and the old version cannot break when it sees data the new version created. That mixed-version window is unavoidable in any zero-downtime strategy, and it is the same discipline as the expand-contract pattern in our zero-downtime migrations guide.

Rolling’s weakness is rollback speed. If the new version is bad, undoing it means rolling back pod by pod, which takes as long as the deploy did — minutes during which a bad release is serving real users. For most services that is fine. For the ones where minutes of a bad release is unacceptable, the other two strategies buy faster escape at a price.

Pipeline of servers representing a rolling deployment
A rolling deploy needs no extra capacity but rolls back as slowly as it rolled out.

Blue-green: instant rollback, at double the cost

Blue-green runs two complete environments. “Blue” is live and serving all traffic; “green” is the new version, fully deployed but receiving nothing. You test green in isolation, then flip a switch — a load balancer target, a DNS record, a Service selector — and all traffic moves to green at once. Blue stays running, untouched.

The payoff is the fastest rollback there is: if green misbehaves, you flip the switch back to blue in seconds, because blue never went away. There is no gradual anything to reverse. That instant escape is the entire reason to choose blue-green.

The price is equally blunt: for the duration of the deploy you run two full production environments, so you pay for double the capacity. And the flip is all-or-nothing — every user moves at once, so if green has a bug that testing missed, everyone hits it in the same instant. Blue-green trades a small, brief cost increase for instant rollback, which is a good deal when downtime is expensive and a wasteful one when it is not.

One subtlety catches teams out: stateful things do not flip cleanly. In-flight sessions, websocket connections, and anything holding local state do not politely move from blue to green. Externalise session state before you rely on this, or the flip drops connections.

Canary: limit the blast radius

Canary deployment attacks a different problem. Rather than making rollback fast, it makes the failure small. You route a slice of traffic — 1%, then 5%, then 25% — to the new version while the rest stays on the old one, watching error rates and latency at each step. If the new version misbehaves, only that slice was affected, and you halt the rollout before it reaches everyone.

# The shape of a canary: weight traffic, watch, increase
- setWeight: 5      # 5% to the new version
- pause: {duration: 10m}   # watch error rate + latency
- setWeight: 25
- pause: {duration: 10m}
- setWeight: 50
- pause: {duration: 10m}
# automated analysis fails the rollout if metrics regress

The strength of canary is that a bad release harms a small fraction of users for a short time, instead of everyone at once. Its cost is complexity: you need traffic splitting, and — this is the part people underestimate — you need automated analysis that can decide whether the canary is healthy. Percentage rollouts without automated metric checks are just a slow blast radius; a human watching a dashboard at 25% is not a control, they are a bystander. Tools like Argo Rollouts or Flagger provide the analysis loop, often driving the traffic split through the same Gateway API weighting used for ordinary routing.

Canary also demands good observability, because it can only protect you if you can tell a healthy canary from a sick one within minutes. If your metrics cannot distinguish a 2% error rate from a 3% error rate quickly, the canary passes and the bad release proceeds anyway.

The database is the hard part of every strategy

Notice what all three strategies quietly assume: that two versions of your code can run at once, or switch instantly, against the same database. That assumption is where most deployment pain actually lives, because a schema change does not roll back the way code does, and it does not run in two versions at once without care.

Consider a rolling deploy where the new version renames a column. For the minutes while both versions serve traffic, the old code writes to the old column name and the new code reads the new one, and something is broken no matter which way the migration ran. A blue-green flip has the same problem in one instant instead of spread over minutes. The deployment strategy you chose does nothing to help here, because the conflict is in the data layer, not the application layer.

The resolution is to decouple schema changes from code changes entirely, using the expand-contract discipline from our zero-downtime migrations guide. You never change a column in the same deploy that changes the code using it. Instead you add the new column in one release, deploy code that writes both old and new, migrate the data, deploy code that reads the new, and only then remove the old column in a much later release. Each intermediate state is compatible with both the version before it and the version after, which is exactly the property every deployment strategy needs from the database and cannot provide on its own.

This is also why rollback is more dangerous than teams expect. Rolling code back is easy; rolling a schema back is often impossible, because the migration may have dropped or transformed data the old code needs. A deploy that couples an irreversible migration to the code release has quietly removed your ability to roll back at all, regardless of how instant your blue-green switch is. The strategy protects the code path; the migration discipline protects the data path, and you need both, because a bad release you cannot undo is not much better than an outage.

Which to choose

Match the strategy to what you are actually afraid of. If you fear cost and your service tolerates a few minutes of imperfect rollback, rolling is correct and needs no extra infrastructure. If you fear downtime and can afford to double capacity briefly, blue-green gives you instant escape. If you fear shipping a subtle bug to your entire user base at once, canary limits the damage — provided you have the observability and automation to run it honestly.

Most organisations end up with a mix: rolling for internal and low-risk services, canary for the handful of critical user-facing paths where a bad release is genuinely expensive, and blue-green reserved for the rare system where an instant, clean switch is worth the doubled cost. None of these is more advanced than the others. They are answers to different fears, and the skill is knowing which fear you actually have. Whichever you pick, the strategy only works if a bad release can be undone faster than it does damage — and that, not the mechanism, is the thing to design for. The same reasoning shows up when a downstream dependency fails mid-deploy, which is where the retry and circuit-breaker patterns earn their place.

← Back to all articles