Progressive delivery means deploying code to production continuously while controlling who actually sees it, using feature flags, canary releases, and staged rollouts. Deploy and release become separate events: engineering ships code on its own schedule, and product management decides exposure — internal, beta, percentage, then general availability — independent of that schedule.
Progressive delivery decouples deploy (code reaches production) from release (users see it). Feature flags create a ladder of exposure — internal, beta, percentage rollout, GA — so shipping daily doesn't mean releasing daily.
Deploy Is Not Release: The Core Distinction
A deploy pushes code onto production servers; a release decides which users can exercise that code. Conflating the two forces every merge into an all-or-nothing bet, whereas separating them lets engineering ship in small, reversible increments constantly while product decides who's exposed and when.
For most of software history, the two words were basically synonyms. Running git merge into main and pushing to production was the release — the moment a feature became real for users. That coupling is why release day carried so much weight: rollback plans, code freezes, weekend deploy windows, and the low-grade dread of shipping something you couldn't easily take back.
Progressive delivery breaks that coupling into two separate questions:
- Is the code in production? An engineering fact, decided by CI/CD pipelines, merge policies, and release engineering.
- Can users see it? A product fact, decided by flag state, audience targeting, and rollout stage.
The evidence behind this shift isn't anecdotal. In the Accelerate research program led by Nicole Forsgren, Jez Humble, and Gene Kim — the basis for the annual DORA State of DevOps reports — elite-performing teams deploy on demand, often multiple times a day, with change failure rates far below teams that deploy monthly or less. Smaller, more frequent, flag-guarded changes correlate with lower risk once "deployed" and "exposed" stop meaning the same thing.
This is the operational core of what the broader move toward continuous, flag-guarded delivery is really about: not a faster version of the old release process, but a different process with a different risk shape entirely.
Picture a pricing-page redesign that touches checkout. Under the old model, it ships whole, on a Thursday, to everyone — and if conversion drops, the team is debugging in production under pressure while revenue is live on the line. Under progressive delivery, the same code deploys behind a flag on Monday, sits off, and gets switched on for 5% of new sessions first. A conversion dip shows up against a tiny slice of traffic, gets rolled back with one toggle, and nobody outside the team ever notices.
The Flag Ladder: From Internal Testing to General Availability
Most mature flag strategies move a feature through four exposure stages — internal, beta, percentage rollout, and general availability. Each rung raises the bar for confidence in stability, usability, and support readiness before the next one opens, so a bad surprise reaches ten people instead of ten thousand.
Think of it as a staircase, not a switch. A feature climbs through stages, and each stage has to answer a specific question before the next one unlocks.
| Stage | Audience | Question it answers | Typical exit signal |
|---|---|---|---|
| Internal | Employees, dogfood users | Does it work at all? | No P0/P1 bugs in daily use |
| Beta | Opt-in or invited users | Is it usable and valuable? | Positive qualitative feedback, low support volume |
| Percentage rollout | 5% → 25% → 50% of base | Does it hold up at scale? | Error rate, latency, support tickets stay flat |
| General availability | 100%, flag removed | Ship it — retire the toggle | Flag deleted from code; it's just "the product" |
Each rung needs an explicit owner and an explicit exit criterion, not a vibe. Skipping a rung — internal straight to 50%, say — is how a bug that ten dogfooding engineers would have caught instead reaches ten thousand paying users.
Choosing who sits in the beta rung deserves as much rigor as choosing what to build. Segmenting a beta cohort by the specific job the feature serves — the kind of segmentation Jobs to Be Done analysis is built for — surfaces sharper signal than a random 2% sample, because you're watching people who actually have the underlying problem use the fix.
Rollout sequencing matters too. Ramping exposure at lower-stakes moments in the customer journey — a settings-page tweak before a checkout-flow change — buys a cheaper place to fail than gating the first cohort purely by traffic volume.
Trunk-Based Development Is the Engineering Prerequisite
Progressive delivery only works if engineers merge small changes directly into a shared trunk multiple times a day rather than living on long-lived branches. Feature flags are what make that safe — they hide unfinished work from users while it's fully integrated. For PMs, this changes what "done" and "velocity" mean sprint to sprint.
Long-lived feature branches are the expensive alternative, and the cost compounds. The longer a branch lives apart from main, the further it diverges, and the eventual merge gets harder, riskier, and more likely to happen in a rush right before a deadline. Feature flags remove the reason to branch for long: incomplete work merges into trunk immediately, hidden behind a flag that's off by default.
In practice, that means:
- Every merge to
mainis small, reviewed, and deployed within hours, not weeks. - Unfinished features live in production code, invisible to users, behind a default-off flag.
- CI validates the whole system on every merge, not one branch's isolated slice of it.
For a PM, this collapses a sequence you may have relied on — "in progress," "code complete," "deployed," "released" — into fewer, more honest states. Code sitting in production tells you almost nothing about whether it delivers value; a merged, flagged-off feature and an unfinished one look identical to a user.
That's a good reason to be wary of deployment frequency or story points as a stand-in for value delivered. Shipping fast and shipping something users need are different claims, and progressive delivery makes that gap more visible, not less.
Write acceptance criteria around user-visible behavior at each flag stage, not around the merge itself. "Deployed behind a flag, off by default" is an engineering milestone worth tracking separately from "available to 10% of segment X," which is a product milestone.
What this does to sprint planning
Sprint boundaries stop being release boundaries once code deploys continuously behind flags. A sprint can end with a feature merged, tested, and live in production at 0% exposure — genuinely done from an engineering standpoint — without a single user having seen it yet.
That's not a failure to ship; it's the point. Resist the instinct to treat "flag still off" as an incomplete sprint. The team's job that sprint was building the capability safely; the rollout decision is separate work with its own timeline, often owned by product rather than tracked against velocity at all.
Canary Releases, A/B Tests, and Percentage Rollouts Aren't the Same Tool
Canary releases, A/B tests, and plain percentage rollouts all expose a feature to a subset of users, but they answer different questions. A canary asks is this safe? using automated health signals and fast rollback. An A/B test asks is this better? using a controlled, statistically powered comparison. A rollout percentage just manages exposure.
| Technique | Primary question | Selection | Success signal | Typical owner |
|---|---|---|---|---|
| Canary release | Is this safe? | Small, often random slice (1-5%) | Error rate, latency, crash rate stay within bounds | Engineering / SRE |
| A/B test | Is this better? | Controlled, statistically powered split | Predefined metric moves significantly | Product + Data/Growth |
| Percentage rollout | Is this ready for everyone? | Sequential ramp (5% → 25% → 50% → 100%) | No regression as exposure grows | Product |
Canarying is release-engineering discipline before it's a product one. Google's Site Reliability Engineering book documents it as automated comparison between a small canary cohort and the rest of the fleet, with rollback triggered the moment metrics diverge. It's asking a narrow, mechanical question: did we break something?
An A/B test asks something harder, and answering it honestly requires real experiment design — a defined hypothesis, a large enough sample, a fixed duration, and a single primary metric chosen before the test starts, not cherry-picked after. A canary rollout dressed up as an "experiment" without that rigor produces a number, just not one worth trusting.
This is also where progressive delivery quietly erodes the line between discovery and delivery. A percentage rollout with instrumentation attached is a live experiment, which means production has become a discovery environment — worth reading against the framing in our guide to balancing discovery and delivery in dual-track agile, since the old assumption that discovery finishes before delivery starts breaks down here.
RedMonk co-founder James Governor coined the term "progressive delivery" in 2018, specifically to name this convergence — canary analysis, feature flags, and A/B testing treated as one connected discipline for controlling exposure, rather than three unrelated tools three different teams happen to use.
The Debt Risk: Stale Flags Are Technical Debt With an Owner Problem
Every flag left in code after its decision is made becomes a small tax: extra branches to reason about, combinatorial QA surface, and — if it's a permission or entitlement flag — a latent security or billing bug. Flags need an explicit owner, an expiration point, and a removal step written into the same story that created them.
Not every flag is supposed to be temporary, and treating them as if they all are is where teams get into trouble. Pete Hodgson's widely cited feature-toggles taxonomy on Martin Fowler's site sorts flags into four categories, and only two are meant to be short-lived.
| Toggle type | Typical lifespan | Purpose |
|---|---|---|
| Release toggle | Days to weeks | Hide in-progress work until launch-ready |
| Experiment toggle | Weeks | Run an A/B test, then resolve |
| Ops toggle | Indefinite | Kill switch for operational risk |
| Permission toggle | Indefinite | Gate features by plan, role, or entitlement |
Debt accumulates specifically in the first two categories when "resolve after launch" never gets scheduled. Every unresolved release or experiment toggle doubles a code path someone has to reason about, multiplies QA surface as flags stack combinatorially, and — if it gates a paid feature or a permission boundary — can quietly become a billing or security bug nobody notices until a support ticket surfaces it.
Teams under-invest in this cleanup for a predictable reason: removing a resolved flag competes for the same sprint capacity as new roadmap work, and it has no visible upside to a stakeholder scanning a release log. Left to compete on perceived impact alone, it always loses — which is exactly why it has to be a rule, not a priority call made fresh each sprint.
Flag hygiene that actually holds up is boring and procedural:
- Register every flag with an owner, a purpose, and an expected removal point at creation time — not as an afterthought.
- Write the removal as a backlog item in the same story that introduces the flag, not a someday-maybe cleanup task.
- Audit flags stuck at 0% or 100% on a fixed cadence — either state, held too long, means the flag has outlived its purpose.
- Distinguish ops and permission toggles explicitly so a cleanup sprint doesn't accidentally delete a kill switch someone still needs.
Making Release a Product Decision, Not an Engineering Event
Once deploy and release are decoupled, "when do we ship" stops being a sprint-end question and becomes an ongoing set of small product decisions: which segment sees this next, what support needs to know first, whether this is ready for the sales deck. That decision belongs to product management, working closely with — but distinct from — whoever operates the flag mechanics.
Deciding that a segment should see a feature next is a product call: it weighs readiness signals, support capacity, marketing timing, and sometimes contractual promises to specific customers. Deciding how the toggle executes that call is an engineering and operational one. Where that line sits is worth being explicit about, and it maps closely onto the broader question of where PM responsibility ends and PO execution begins on a delivery team.
In practice this means a short, recurring checklist before any flag advances a rung:
- Support is briefed on what's changing and what to say if a user notices something different.
- The exit metric from the previous stage actually held, not just "nothing exploded."
- Marketing or sales knows if this segment's exposure change should be visible externally at all.
- A rollback owner is named for the window immediately after the toggle flips, not just a rollback plan filed somewhere.
None of that checklist requires new tooling — it requires treating each rung of the ladder as a real decision with real accountability, the same way a launch used to get one.
The mental shift underneath all of this: release stops being an engineering event you attend and becomes a product decision you make — repeatedly, in small increments, with a rollback available the whole time.
This is also why rollout planning works best when it's written down next to a feature's intent, not improvised after the code is merged. Prodinja's Spec Studio lets you capture rollout criteria and guardrails — which segment needs to reach which flag stage, what exit metric gates the next one — as spec sections alongside the problem statement and acceptance criteria, so the flag strategy for a feature is defined alongside its intent instead of bolted on afterward in a chat thread.
Key Takeaways
- Deploy and release are different events — code reaching production and code reaching users are decisions with different owners and different risk profiles.
- The flag ladder — internal, beta, percentage, GA — turns exposure into staged decisions with exit criteria, not one high-stakes switch.
- Trunk-based development is the engineering enabler: merging small, flagged-off changes into
maindaily is what makes safe continuous deployment possible. - Canary releases, A/B tests, and percentage rollouts answer different questions — safety, superiority, and readiness, respectively — and conflating them produces results you shouldn't trust.
- Stale flags are technical debt with a name and an owner problem: register every flag with an expiry and schedule its removal at creation time, not after.
- Release is a product decision, not an engineering milestone — treat "who sees this next, and why" as ongoing product work, not a one-time launch event.
Frequently Asked Questions
What's the difference between continuous deployment and progressive delivery?
Continuous deployment automates getting code into production; progressive delivery controls who is exposed to it once it's there. You can run continuous deployment without progressive delivery — every deploy goes straight to 100% of users — it's just riskier, since you lose the staged exposure feature flags provide.
How many users should be in a canary release?
There's no universal number. Most teams start canaries around 1-5% of traffic — large enough to be statistically meaningful for the metrics being watched (error rate, latency, crash rate), small enough that a bad canary affects few real users. Google's SRE practice ties canary size to how quickly automated monitoring can detect a regression, not to a fixed percentage.
Who decides when a feature flag goes to 100%?
In most healthy setups, product management owns the decision to advance a flag stage based on that rung's exit criteria, while engineering owns the mechanism that executes it safely. Ambiguity here is usually a sign the exit criteria were never written down in the first place.
Do feature flags replace QA and testing?
No — feature flags reduce the blast radius of a mistake; they don't reduce the likelihood of one. Automated testing, code review, and staging environments still catch what a flag can't: a flag guards who sees a bug, not whether the bug exists in the first place.
How long should a feature flag live before it's considered stale?
For release and experiment toggles, most teams treat anything still active more than a few weeks past its resolution point as stale — the exact window matters less than having one at all and auditing against it. Ops and permission toggles are the exception: they're meant to live indefinitely and shouldn't get swept into the same cleanup.