What is it? #
A deployment strategy decides how a new version replaces the old one and how much exposure a bad version gets before you notice.
Recreate stops the old and starts the new — simple, with downtime. Rolling replaces instances gradually. Blue-green runs two complete environments and switches. Canary sends a small share of traffic to the new version first.
The trade is always the same: less risk costs more infrastructure and more complexity.
Feature flags sit alongside all of them and often reduce the need for a risky deployment entirely, by separating deploying code from enabling behaviour.
Think of it like this #
Changing the tyres on a vehicle.
Stopping completely is recreate. Changing one wheel at a time while moving slowly is rolling. Having a second identical vehicle ready and switching drivers is blue-green. Letting one passenger try the new vehicle first is canary.
Simple example #
A team starts with recreate on one server, moves to rolling with two servers behind a load balancer, and later adopts canary for risky releases while using feature flags for anything user-visible.
Code #
RECREATE stop old, start new
▓▓▓▓ → ░░░░ → ████ downtime: seconds to minutes
simplest; acceptable for internal tools and low-traffic systems
ROLLING replace instances one at a time
████ ▓▓▓▓ ▓▓▓▓
████ ████ ▓▓▓▓ no downtime; both versions run together
████ ████ ████ needs backwards-compatible code and schema
BLUE-GREEN two full environments, switch traffic
blue ▓▓▓▓ (live) → green ████ (live)
instant switch, instant rollback; doubles infrastructure during deploy
CANARY a small share of traffic to the new version
95% ▓▓▓▓ 5% ████ → monitor → 50/50 → 100%
smallest blast radius; needs traffic routing and good metrics
Choosing
downtime rollback infra cost complexity needs
recreate yes redeploy 1x lowest nothing
rolling no gradual 1x + 1 low load balancer
blue-green no instant 2x briefly medium routing switch
canary no instant 1x + a bit highest routing + metrics
Most teams: recreate for internal tools, rolling for normal services,
canary for the riskiest changes.
What every strategy except recreate requires
Both versions run simultaneously, so:
- the database schema must work for both versions
- API changes must be additive, not breaking
- shared caches must tolerate both versions' data shapes
- background jobs queued by one version must be processable by the other
This is the real constraint. The routing is the easy part.
# Feature flags: deploy the code, enable the behaviour separately
def checkout(user, cart):
if flags.enabled("new-pricing-engine", user=user):
total = new_pricing.calculate(cart)
else:
total = legacy_pricing.calculate(cart)
return process(total)
# Deploy disabled → enable for staff → 5% of users → everyone.
# Disabling is instant and does not require a deployment.
Canary: what to watch, and for how long
error rate compared with the stable version, not an absolute number
latency p95 a regression here is often the first signal
business metrics conversions, signups — technical health can look fine
while the feature quietly breaks something
Watch for long enough to cover a realistic traffic mix. Five minutes at
2am proves less than five minutes at peak.
How it works #
Recreate is the simplest and the only one with downtime. For a single server with an application that restarts in ten seconds, it is often the honest choice.
Rolling replaces instances one at a time behind a load balancer. There is always capacity serving, and both versions run simultaneously for a period — which is the constraint that matters.
Blue-green keeps two complete environments. Deploy to the idle one, verify it properly, then switch traffic. Rollback is switching back, which is close to instant, and the cost is running two environments during the deployment.
Canary routes a small percentage of traffic to the new version and increases it if the metrics stay healthy. It gives the smallest blast radius and requires both traffic routing and metrics good enough to compare the two versions.
The shared constraint is compatibility. In every strategy except recreate, two versions serve simultaneously, so the schema, the API and the job queue must work for both. Teams usually discover this the first time a rolling deployment breaks because the new version wrote a job the old version could not process.
Feature flags change the calculation. Deploying code that is switched off carries little risk, and enabling it is a configuration change that can be reversed in seconds. Much of what canary deployments are used for can be achieved with a flag and a simpler deployment.
Canary evaluation should compare against the stable version rather than an absolute threshold, because baseline error rates are never zero.
Real-world use #
Most teams do not need blue-green or canary. Rolling deployment with health checks and fast rollback covers the large majority of cases.
Feature flags are the higher-leverage investment for most products. They decouple deployment from release, which makes deployments boring and releases controllable.
Flag debt is real. Flags that were meant to be temporary accumulate, and each one doubles the number of code paths. Removing them after full rollout should be part of the process.
Database compatibility is the recurring constraint across all of this. Expand-and-contract migrations are what make any zero-downtime strategy viable.
The best strategy is the simplest one that meets the risk requirement. Adopting canary before you have reliable metrics produces complexity without the benefit.
Common mistakes #
- Adopting canary without metrics good enough to compare versions.
- Forgetting that two versions run simultaneously in every strategy but recreate.
- Breaking API or schema compatibility during a rolling deployment.
- Accumulating feature flags and never removing them.
- Evaluating a canary against an absolute error threshold rather than the stable version.
Practice #
For a system you know, decide which strategy fits and justify it. Then list every compatibility requirement that running two versions simultaneously would impose: schema, API, cache and job queue. Finally, identify one recent risky change that a feature flag would have made safer.