Origins
For most of software history, a release was a moment — a date on a calendar, a marketing campaign, a deployment window in the middle of the night, and a war room with pizza. The waterfall release was an event because the cost of getting it wrong was catastrophic, and the cost of getting it right meant not doing it very often.
Incremental release practices invert that bargain. Drawing on the work of Jez Humble and David Farley in Continuous Delivery (2010), the Flickr engineering team’s “ten deploys a day” talk (Allspaw and Hammond, 2009), and decades of Etsy, Netflix, and Google practice,1 these techniques aim to make any individual release so small, so observable, and so reversible that shipping becomes routine.
The Underlying Principle
The deeper move behind every incremental release pattern is the same: separate deployment from release. Deployment is the act of moving code into a production environment. Release is the act of exposing that code to users. Treating them as one event is what makes releases scary. Treating them as separate is what makes them safe.
Once that separation exists, an entire toolkit opens up:
- Feature flags let code travel to production dormant, ready to be turned on without redeploying.
- Dark launches run new code paths in production silently, comparing outputs to the live system without affecting users.
- Canary releases expose the new version to a small slice of traffic, watching telemetry before expanding.
- Progressive rollouts grow that slice on a schedule — 1%, 5%, 25%, 100% — with explicit pause and rollback gates.
- Blue-green deployments run two production environments in parallel, swapping traffic between them.
Feature Flags
The most fundamental of the incremental tools. A flag is a switch that controls whether a path of code runs. With flags, the team can:
- Merge unfinished features to
mainwithout exposing them — keeping the branch model simple and trunk-based. - Roll out by cohort, geography, plan, or percentage.
- Kill a misbehaving feature in seconds, without a deploy.
- Run A/B experiments alongside production traffic.
The cost is flag debt: every flag is a fork in the code. Healthy teams budget time to retire flags as aggressively as they create them. A flag that has been at 100% for three months is no longer a switch — it is clutter pretending to be a switch.
Dark Launches and Shadow Traffic
Some changes are too consequential to test only in staging — database migrations, search relevance changes, ranking algorithms. A dark launch runs the new code in production but does not act on its output: results are logged and compared, not served. This catches performance regressions, edge cases in real data, and behavior diffs before any user sees them.
Facebook famously dark-launched its Chat product for weeks before turning it on — running the back end against real traffic patterns while the front end was hidden.2 That kind of pre-flight is now routine in any system where mistakes in production are expensive to reverse.
Canaries and Progressive Rollouts
Where flags decide who sees a change, canaries decide how confidently it is exposed. A canary sends a small percentage of traffic — often 1% — to the new version, while the bulk of users remain on the previous one. The team watches the difference: error rates, latency, key conversions. If the canary is healthy, the percentage expands. If not, it is reverted before most users ever notice.
Progressive rollouts formalize this into a schedule. Each step has an entry criterion (telemetry healthy, no error spike) and a dwell time (long enough to catch slow-burn problems). The discipline of the rollout matters more than the exact percentages — the point is to slow down at the moment teams are most tempted to speed up.
Reversibility as a Design Goal
Every incremental practice exists in service of one property: reversibility. The team should be able to undo a release in less time than it took to detect the problem. That changes everything upstream — from the way features are decomposed to the way schemas are migrated to the way the team feels at 4 PM on a Friday.
Reversibility does not happen by accident. Database migrations need to be backward-compatible across at least one version. APIs need versioning or expansion-before-contraction. The deploy pipeline needs a one-click rollback that the team has actually rehearsed.
Coaching Tips
Make the deploy boring on purpose.
The goal is not heroism but predictability. If a deploy has a dramatic story, dig into why.
Budget time for flag retirement.
Schedule a recurring task — every sprint, kill at least one flag that no longer needs to exist.
Rehearse the rollback.
A rollback you have never run is theater. Test it on a low-stakes change so the team trusts it.
Watch the canary, not the dashboard.
During rollout, the metric that matters is the diff between cohorts — not the absolute number.
Make schema changes additive first.
Add the new column, double-write, migrate, then drop the old. Three small deploys beat one big one.
Pause the rollout deliberately.
Build a dwell time into each step. The bugs you are looking for often need an hour to show up.
Summary
Incremental release practices are not a single technique but a stance: every change should be small enough, observable enough, and reversible enough that shipping stops being interesting. The teams that get good at this discover an unexpected secondary effect — they ship more often and more calmly. Risk is not removed; it is spread thinly across many small acts rather than concentrated in a few large ones.
- Humble, Jez and David Farley. Continuous Delivery. Addison-Wesley, 2010.
- Letuchy, Eugene. “Facebook Chat.” Engineering @ Facebook blog, 2008.
- Forsgren, Nicole, Jez Humble, and Gene Kim. Accelerate. IT Revolution, 2018.