Build the mental model
Once you can deploy a new version, you need a way to roll it out safely and pull it back if something goes wrong. Three patterns cover most real-world rollout strategies.
Rolling deployment gradually replaces old instances with new ones, a few at a time, so the app stays available throughout — the tradeoff is that old and new versions run side by side briefly, which can be risky if they aren't compatible.
Blue-green deployment keeps two full environments: Blue is the current production version, Green is the new version, tested in parallel while Blue keeps serving real traffic. Once Green looks healthy, traffic switches over all at once; if a problem appears, traffic switches straight back to Blue, which is still fully running.
Canary deployment sends a small percentage of real users — say 5 percent — to the new version first, watches error rates and performance, and only increases that percentage once the new version proves itself, stage by stage.
| Strategy | Tradeoff |
|---|---|
| Rolling | Simple and resource-efficient, but mixes versions during rollout |
| Blue-Green | Fastest, cleanest rollback, but doubles infrastructure cost while both environments run |
| Canary | Most gradual risk exposure, but takes longer to fully roll out and needs good monitoring |
None of these wins outright
Not every platform supports every one of these models — some PaaS-style platforms only offer one built-in strategy. The CI/CD with GitHub Actions tutorial's deployment-strategies and rollback-and-recovery lessons cover how to actually implement each pattern.
THREE ROLLOUT / ROLLBACK PATTERNS
---------------------------------
ROLLING DEPLOYMENT
[old][old][old][old] -> replace one at a time ->
[new][old][old][old] -> [new][new][old][old] -> ...
rollback = replace new->old again, same way, takes time
BLUE-GREEN DEPLOYMENT
BLUE (current, live) <---- traffic
GREEN (new, tested in parallel, not yet live)
switch: traffic ----> GREEN (all at once)
rollback: traffic ----> BLUE (instant, Blue still running)
CANARY DEPLOYMENT
stage 1: 95% old / 5% new -- watch error rate
stage 2: 75% old / 25% new -- watch error rate
stage 3: 0% old /100% new -- fully rolled out
rollback: new% -> 0 at any stage once errors spikeConnect it to a real scenario
Understanding these patterns matters most when something breaks in production, because your rollback speed depends entirely on which pattern is running.
| Strategy | Rollback speed |
|---|---|
| Rolling | Means running the rollout in reverse — takes time proportional to fleet size and step count |
| Blue-Green | Close to instant — traffic simply points back at the Blue environment, which was never torn down |
| Canary | Dropping the new version's traffic percentage back to zero, but only after the canary stage has actually caught the problem |
When picking a platform, ask not just "can it deploy new code" but "what does rolling back actually look like here, and how fast."
A platform that only supports one pattern may still be fine if that pattern matches how cautious you need to be — the right choice depends on traffic volume, how costly a bad deploy would be, and how much infrastructure duplication your budget tolerates.
Try the working example
function simulateCanaryRollout(startPercent, stepSchedule, errorRateAtStage, errorThreshold) {
let currentPercent = startPercent;
const log = [];
for (let i = 0; i < errorRateAtStage.length; i++) {
const errorRate = errorRateAtStage[i];
log.push({ stage: i + 1, canaryPercent: currentPercent, errorRate });
if (errorRate > errorThreshold) {
log.push({ stage: i + 1, decision: "ROLLBACK", reason: `error rate ${errorRate} exceeded threshold ${errorThreshold}` });
return { finalPercent: 0, rolledBack: true, log };
}
// Error rate is acceptable at this stage: move to the next step, if any.
if (i < stepSchedule.length) {
currentPercent = stepSchedule[i];
}
}
return { finalPercent: currentPercent, rolledBack: false, log };
}
// Scenario A: a healthy rollout that completes.
const healthy = simulateCanaryRollout(
5,
[25, 50, 100],
[0.2, 0.3, 0.25, 0.2],
1.0
);
console.log("Healthy rollout:", JSON.stringify(healthy, null, 2));
// Scenario B: errors spike partway through and trigger a rollback.
const risky = simulateCanaryRollout(
5,
[25, 50, 100],
[0.3, 4.8],
1.0
);
console.log("Risky rollout:", JSON.stringify(risky, null, 2));Healthy rollout: finalPercent 100, rolledBack false — all 4 stages stayed under the error threshold.
Risky rollout: stage 2's error rate of 4.8 exceeded the threshold of 1.0, so rolledBack is true and finalPercent is 05-minute try-it
Modify the errorRateAtStage array and test with values close to the threshold — see exactly when the function decides to roll back
One important caution
Ignoring that too small a canary traffic percentage can take a long time to actually detect a problem
Assuming every platform can give you blue-green's instant rollback without accounting for the doubled infrastructure cost
Martin Fowler: BlueGreenDeployment — Cloud Providers & Platforms