Deploying is not releasing
Deployment puts code on a machine. Release exposes behaviour to a user. Treating them as one event is why rollbacks are frightening, why releases happen at night, and why a bad feature requires an emergency deploy instead of a config change.
TL;DR: Separate the two and the properties you want fall out: deploys become frequent, boring and reversible, while releases become a runtime decision with a blast radius you choose. The mechanism is a flag, and the cost is discipline about removing them.
The coupling and what it costs
When shipping code and exposing behaviour are the same act, several things follow that nobody chose:
- Every release carries the risk of every code change in it, so releases get batched, and batching makes each one riskier still.
- Turning a feature off means deploying, which takes as long as your pipeline takes, during an incident.
- A feature cannot be tested against production traffic before users see it.
- Releases happen when the risk is lowest rather than when the work is ready, which is how deploy windows and Friday freezes appear.
Every one of those is a symptom of the coupling rather than a fact about software.
What separation makes possible
Dark launch. Deploy the new code path, run it on an approved copy of real traffic, suppress external writes and notifications, and compare its output against the old path. Protect personal data and account for the extra load. You learn whether it works under production load before anyone depends on it.
Progressive exposure. One percent, then ten, then half, watching the metrics you care about. The blast radius of a bad release becomes a number you set.
Fast exposure rollback. A flag flip can stop new exposure after configuration propagates; test that delay and the fallback when the flag service is unavailable. This is the property that makes the whole thing worth it, because mitigation speed is what bounds an incident.
Targeting. Internal staff first, then a beta cohort, then everyone. The people best able to report a problem see it first.
Decoupled ownership. Product decides when a feature is on. Engineering decides when code ships. Those are different decisions made by different people on different timescales, and merging them serves neither.
The costs, stated honestly
Flags are conditional branches, and conditional branches are complexity. Two flags interact in four ways; ten interact in more ways than anyone tests. Untested combinations are where surprising bugs live.
Flags also rot. A flag that has been at 100 percent for eight months is dead code with a runtime switch attached, and the switch still works, which is the danger. Somebody will find it.
So the discipline: every temporary release flag gets an owner and removal date at creation, and removal is planned once the rollout is stable, and the flag inventory is reviewed on a schedule. Deliberate operational kill switches may remain, with owners and tests for both states. A team that adds flags and never removes them has traded one problem for a worse one.
Not everything can be flagged
A schema migration is not a flag. Neither is a message format change, an external side effect already sent, or a cache whose entries the old code cannot read. Those need expand and contract, versioned formats, and sequencing across releases.
Knowing which changes are flaggable and which need a migration strategy is the actual skill. A team that believes flags make every change reversible will eventually contract a column behind one and discover otherwise.
The connection to everything else
Separating exposure from deployment gives progressive delivery another control. Continuous deployment can also safely release small compatible changes directly, using tests, canaries and recovery controls. Flags are useful where selective exposure matters; they are not a prerequisite for every safe deployment.
Self-check
Can a shadow checkout safely call the payment provider if its HTTP response is discarded? No. Discarding output does not undo a charge. Suppress or sandbox the side effect before duplicating production traffic.