Blue-Green vs Canary vs Rolling Deployments
Three ways to release a new version without taking your app down or betting everything on it working. How blue-green, canary and rolling deployments work, what each needs, how they handle database migrations, and a pragmatic approach for a small app on one or two servers.
The naive deploy — stop the old version, start the new one — causes a few seconds (or minutes) of errors, and if the new version is broken, every user sees it immediately. Deployment strategies fix both problems in different ways. (Zero-downtime deploys)
Rolling deployment
Replace instances one (or a few) at a time. With four instances, update one, wait until it's healthy, then the next.
- ✅ No extra servers needed; no downtime if you have more than one instance.
- ❌ Old and new versions run side by side during the rollout, so they must be compatible.
- ❌ Rolling back means rolling forward again with the old version.
The default in Kubernetes, Docker Swarm and many platforms. (Do you need Kubernetes?)
Blue-green deployment
Run two complete environments:
- Blue — the live version, getting all traffic.
- Green — the new version, deployed and tested while getting no real traffic.
When green passes its checks, switch the load balancer or proxy to green, all at once. Blue stays running, untouched.
┌─ blue (v1) ← traffic
proxy ────┤
└─ green (v2) ← deploy and test here, then switch
- ✅ Instant rollback: switch back to blue.
- ✅ Test the new version in production conditions before users see it.
- ❌ Needs capacity for two full environments (briefly).
- ❌ All users switch at once — a bug not caught by tests hits everyone.
Canary deployment
Send a small percentage of traffic to the new version — 1%, then 5%, 25%, 100% — while watching error rates and latency. If metrics look bad, send everyone back to the old version.
- ✅ A bad release affects only a few users, briefly.
- ✅ Catches problems tests miss, using real traffic.
- ❌ Needs traffic splitting and good monitoring to decide automatically or quickly. (What is OpenTelemetry?, Error monitoring)
- ❌ Needs enough traffic for small percentages to be meaningful.
Named after canaries in coal mines.
Side by side
| Rolling | Blue-green | Canary | |
|---|---|---|---|
| Extra capacity | Little | 2× briefly | A little |
| Rollback speed | Slow (redeploy) | Instant | Fast |
| Blast radius of a bug | Grows during rollout | Everyone at switch | Small, controlled |
| Old + new run together | Yes | Briefly | Yes, for the whole rollout |
| Complexity | Low | Medium | Higher (needs metrics) |
The hard part: the database
All three strategies share one database, and in rolling and canary deploys both versions use it at the same time. So schema changes must be backward compatible:
- Expand — add new columns/tables; don't remove or rename anything the old version uses.
- Deploy the new code, which works with the expanded schema.
- Migrate data if needed.
- Contract — in a later deploy, remove what the old version needed.
Renaming a column in one step breaks whichever version doesn't expect it. (Postgres migrations on large tables, Prisma migrations in production)
Feature flags: a different lever
Feature flags separate deploying code from releasing features: ship code turned off, then enable it for 1% of users, then everyone. Canary-like control at the feature level, without traffic routing. (Feature flags)
For a small app on one server
You don't need Kubernetes for most of this:
- Blue-green on one server: run the new version on a second port, check its health endpoint, switch the reverse proxy's upstream, stop the old one. (Health check endpoints, Nginx reverse proxy config)
- Graceful shutdown so in-flight requests finish. (Graceful shutdown in Node.js)
- Preview environments per branch to test before merging. (Preview environments for every branch)
- Feature flags for risky features.
That covers most of the benefit with very little machinery.
EasySpawn gives every branch a live preview URL on your server and runs production behind a reverse proxy with health checks — the building blocks for safe releases without a platform team. See how it works or join the waitlist.
Related: Zero-Downtime Deploys for a Small App · Feature Flags for Small Teams · Preview Environments for Every Branch · Health Check Endpoints
Keep reading
Is SQLite Good Enough for Production? When It Works and When It Doesn't
SQLite now runs real production apps. When a single-file database is a great choice, the settings you must change (WAL mode, busy timeout, foreign keys), backups with Litestream, the single-writer limit, and the hosting setups where SQLite will lose your data.
Health Check Endpoints: What /health Should (and Shouldn't) Check
A health check endpoint tells load balancers, orchestrators and monitors whether your app can serve traffic. Liveness vs readiness, what to check and what not to, response formats, timeouts, security, and examples for Express, Next.js and Docker.