A canary deployment routes a small percentage of traffic to a new version while most users continue on the stable version — letting you catch problems with real production traffic before a full rollout, limiting the blast radius if something's wrong.
Canary vs Blue-Green
| Factor | Blue-Green | Canary |
|---|---|---|
| Traffic split | All-or-nothing switch | Gradual percentage-based rollout |
| Risk exposure | 100% of traffic hits new version immediately after switch | Only a small % initially exposed to any issue |
| Complexity | Simpler to implement | More complex traffic control needed |
Prerequisites
- Nginx as a reverse proxy
- Multiple versions of your application running simultaneously
Step 1 — Run Both Versions
services:
app-stable:
image: myapp:v1.2.0
ports:
- "3001:3000"
app-canary:
image: myapp:v1.3.0
ports:
- "3002:3000"
Step 2 — Configure Weighted Load Balancing in Nginx
upstream backend {
server 127.0.0.1:3001 weight=9;
server 127.0.0.1:3002 weight=1;
}
This sends roughly 10% of traffic to the canary version, 90% to stable — Nginx's weighted round-robin distributes requests proportionally.
Step 3 — Apply and Monitor
sudo nginx -t && sudo systemctl reload nginx
Watch error rates, response times, and application logs specifically for the canary instance during this period.
Step 4 — Gradually Increase Canary Traffic
upstream backend {
server 127.0.0.1:3001 weight=7;
server 127.0.0.1:3002 weight=3;
}
Increase the canary's share incrementally (10% → 30% → 50% → 100%) over a period of hours or days, monitoring at each stage before proceeding.
Step 5 — Complete the Rollout
upstream backend {
server 127.0.0.1:3002;
}
Once confident, route 100% of traffic to the new version, and the previous stable version becomes the new canary target for the next release cycle.
Step 6 — Roll Back If Issues Appear
upstream backend {
server 127.0.0.1:3001;
}
Simply revert the weights — if you caught the issue early during the canary phase, only a small fraction of users were ever affected.
Routing Specific Users to Canary (More Sophisticated)
Rather than random percentage-based splitting, route based on a cookie or header — useful for opt-in beta testing or ensuring internal team members always hit the canary:
map $cookie_canary $backend_pool {
"true" canary_backend;
default stable_backend;
}
Monitoring Metrics to Watch During a Canary Rollout
- Error rate (should not increase compared to stable)
- Response time (should remain comparable)
- Application-specific business metrics if relevant (conversion rate, etc.)
Automating Canary Analysis
For more sophisticated setups, tools exist that automatically compare canary vs stable metrics and decide whether to proceed or roll back — for simpler VPS-based deployments, manual monitoring during each stage is often sufficient and more transparent.
Common Errors
Uneven traffic distribution — Nginx's weighted round-robin is proportional but not perfectly random per-request over small sample sizes; over sufficient traffic volume it converges to the configured ratio.
Session inconsistency — if your app uses server-side sessions without a shared store, a user might bounce between canary and stable on different requests, causing inconsistent behavior; use a shared session store (Redis) to avoid this.
Best Practices
- Start with a small canary percentage (5-10%) and increase gradually
- Actively monitor during each stage, not just at the end
- Have a fast rollback plan ready before starting the rollout
Continue Reading
- How to Set Up Blue-Green Deployment on a VPS
- How to Set Up Basic Load Balancing with Nginx
- How to Roll Back a Bad Deployment Quickly
Browse more articles in DevOps & CI/CD.
