Blue-Green vs Canary Deploys for Small Teams
10 Feb 2026Neither blue-green nor canary is the default answer. For a team running five servers, a plain rolling restart with a healthcheck covers almost every case, and the two fancier strategies solve problems you probably don’t have yet.
What each one actually is
Blue-green: run two identical full environments, “blue” (live) and “green” (idle). Deploy to green, verify it, then flip all traffic to green at once. Blue stays up as an instant rollback target.
Canary: deploy the new version to a small slice of your infrastructure — one server out of five, or 5% of traffic — and watch error rates and latency before rolling it out further.
Rolling restart: replace instances one at a time, each one passing a healthcheck before traffic shifts to it and the old one stops. This is what Docker Swarm and Kubernetes do by default when you set an update policy and a healthcheck.
The comparison
| Blue-green | Canary | Rolling | |
|---|---|---|---|
| Infra cost | 2x during deploy | Small overhead | None extra |
| Rollback speed | Instant (flip back) | Fast (kill the canary) | Fast (redeploy old image) |
| Catches bugs before full rollout | No — all-or-nothing | Yes — partial exposure | Partially — first instance is a de facto canary |
| Setup complexity | Needs a router/LB that can flip instantly | Needs traffic splitting + metrics to auto-decide | Needs a healthcheck and an update policy |
| Good fit | Zero-tolerance for bad deploys, have the infra budget | Gradual exposure with real metrics gating rollout | Small teams, most day-to-day deploys |
Why rolling is enough at five servers
Canary’s whole value is statistical: you want a bad deploy to affect 5% of traffic, not 100%, while you watch dashboards and decide whether to proceed. That only works if 5% of your traffic is a meaningful sample and you have monitoring sensitive enough to catch a regression in that slice before it matters. At five servers, “5% of traffic” is a fraction of one server’s worth of requests — not enough signal to distinguish a real regression from noise. You’d be adding complexity to get a signal you can’t actually read.
Blue-green’s value is instant, atomic rollback and testing the full new environment before it’s live. That matters when a bad deploy is expensive per minute — payment processing, high-traffic consumer apps. It costs double the infrastructure during every deploy, which is a real bill, not a rounding error, when you’re running five servers instead of five hundred.
Rolling restart with a real healthcheck gets you most of the benefit of both at close to none of the cost:
# docker-compose deploy config, Swarm mode
deploy:
update_config:
parallelism: 1
order: start-first
failure_action: rollback
delay: 10s
rollback_config:
parallelism: 1
order: stop-first
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 10s
timeout: 3s
retries: 3
start_period: 30s
order: start-first means the new instance starts and passes its healthcheck before the old one stops — that’s your zero-downtime guarantee. failure_action: rollback means if the new instance never goes healthy, Swarm reverts automatically instead of leaving you at a broken instance count.
When to actually upgrade
Move to canary when you have enough traffic and observability that a 5-10% slice gives you a real signal within minutes, and a deploy that goes wrong is expensive enough to justify the setup — feature flags tied to metrics dashboards, automated rollback on error-rate threshold.
Move to blue-green when a deploy failure is costly enough per minute that doubling infrastructure cost during the deploy window is clearly cheaper than the downside, or when your app can’t tolerate mixed-version traffic during a rolling window (two versions of your API serving different clients simultaneously, with incompatible contracts).
Takeaway
Rolling restart plus a real healthcheck is the unglamorous right answer for most small teams. Canary and blue-green are correct escalations once traffic volume and deploy risk justify their cost — not defaults to reach for because they sound more serious.