# Deployment Strategies Compared: Rolling, Canary, Blue-Green
Shipping new code is the moment your service is most likely to break. The *deployment strategy* you choose determines how much blast radius a bad release has, how fast you can roll back, and how much extra infrastructure you pay for. Let's compare the three you'll actually use — rolling, blue-green, and canary — plus a couple of variants.
The baseline problem
A naive deploy stops the old version and starts the new one ("recreate"). It's simple but causes downtime and offers no safe rollback if the new version is broken. Every strategy below exists to avoid that.
Rolling deployment
Replace instances gradually: spin up some new-version instances, shift traffic, retire old ones, repeat until everything is upgraded.
[v1][v1][v1][v1]
[v2][v1][v1][v1] ← replace one at a time
[v2][v2][v1][v1]
[v2][v2][v2][v2] ← done- Pros: No downtime, no extra infrastructure (reuses the same capacity), simple, the Kubernetes default.
- Cons: During the rollout, both versions serve live traffic simultaneously — your code and database must be compatible across versions. Rollback means rolling *back* gradually, which is slower than an instant switch.
Kubernetes does this natively:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 0Blue-green deployment
Run two complete environments: blue (current, live) and green (new). Deploy and fully test green while blue serves all traffic, then flip the router to send 100% of traffic to green. Blue stays around as an instant rollback target.
Blue (v1) ← all traffic
Green (v2) ← warming up, tested
── flip ──▶
Blue (v1) ← idle (rollback target)
Green (v2) ← all traffic- Pros: Instant cutover, instant rollback (flip back to blue), and you can fully smoke-test green before any user sees it.
- Cons: Doubles infrastructure during the deploy. Database migrations are tricky because both environments may share one database — schema changes must work for both versions.
Canary deployment
Release the new version to a small fraction of users first (say 5%), watch metrics, and gradually increase if healthy — or roll back if not.
95% → v1
5% → v2 ← watch error rate, latency
... healthy? increase to 25%, 50%, 100%
... unhealthy? route back to 100% v1- Pros: Smallest blast radius — a bad release affects only a sliver of users. Real production validation with real traffic. Pairs beautifully with automated metric-based promotion/rollback.
- Cons: Most complex. Requires fine-grained traffic control, solid observability to *judge* canary health, and (like the others) cross-version compatibility.
Side-by-side
| Strategy | Downtime | Extra infra | Rollback speed | Blast radius | Complexity |
|---|---|---|---|---|---|
| Recreate | Yes | None | Slow | Full | Lowest |
| Rolling | No | None | Medium (roll back) | Gradual | Low |
| Blue-green | No | 2× during deploy | Instant | Full (after flip) | Medium |
| Canary | No | Small extra | Fast (re-route) | Tiny | High |
Don't forget the database
Every zero-downtime strategy shares one hard constraint: old and new code run against the same database at once. That forces *backward-compatible*, expand/contract migrations:
- 1Expand: add the new column/table; deploy code that writes to both old and new.
- 2Migrate: backfill data.
- 3Contract: once all instances are on the new version, drop the old column.
A migration that renames a column in one step will break whichever version doesn't expect it. This is the most common cause of "the deploy strategy was fine but the release still broke."
Choosing
- Rolling — sensible default for most services; zero-downtime with no extra cost.
- Blue-green — when you need instant rollback and can afford temporary double capacity; great for releases you want to fully smoke-test first.
- Canary — for high-traffic, high-stakes services where you want to limit blast radius and can invest in observability and automation.
Many teams combine them: blue-green for the *infrastructure*, canary for the *traffic shifting* into green.
Feature flags: the orthogonal tool
Worth noting that feature flags decouple *deploy* from *release*. You can ship code dark (deployed but flagged off) via any strategy above, then turn the feature on for a cohort independently. Deploy strategy controls *which code runs*; feature flags control *which behavior is visible*. They compose well.
Deploys on PandaStack
PandaStack deploys via Helm onto multi-region GKE, which gives you zero-downtime rolling updates out of the box, plus rollbacks and deploy history so reverting to a previous release is a click — the instant-rollback property blue-green is prized for, without you running two environments by hand. Live build and app logs let you watch a release land and judge its health. For staged traffic, you can validate changes on instant previews (pandastack.ai) before promoting.
References
- [Kubernetes — Deployment strategies](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
- [Martin Fowler — BlueGreenDeployment](https://martinfowler.com/bliki/BlueGreenDeployment.html)
- [Martin Fowler — CanaryRelease](https://martinfowler.com/bliki/CanaryRelease.html)
- [Argo Rollouts — progressive delivery](https://argo-rollouts.readthedocs.io/)
- [Google SRE Book — Release Engineering](https://sre.google/sre-book/release-engineering/)
Want zero-downtime deploys and one-click rollbacks without writing Helm? PandaStack's free tier handles it from a Git push. [Start at dashboard.pandastack.io](https://dashboard.pandastack.io).