The Feature Flag
Deploy is a technical event. Release is a business decision. Never confuse them again.
The incident
The new checkout went to 100% of users in one deploy. The bug appeared under real traffic within minutes. The rollback was a new deployment — which meant a build, a pipeline, and an hour of every customer seeing the broken flow while the pipeline ran.
Why the obvious approach fails
When deploy and release are the same event, every release is a bet at full stakes, and your rollback speed is your pipeline speed — minutes to hours, during which the damage compounds. It also creates release-train paralysis: risky changes wait, batch up, and ship together, making each release bigger and riskier. Decoupling the two turns release into a dial: code ships dark, turns on for 5%, earns its way to 100% against live metrics, and turns off in seconds if it misbehaves — no pipeline involved.
The standard
- Risky or user-facing changes ship behind flags; deploy-equals-release is the exception and requires justification.
- Rollout is progressive with declared gates: internal → 5% → 25% → 100%, each gate tied to error and metric thresholds.
- Every flag has a kill switch honored in seconds from a control panel — no deployment in the disable path.
- Targeting supports segments (internal users, beta cohort, tenant) for controlled exposure.
- Flags have owners and expiry dates; a flag registry prevents the codebase from fossilizing into flag spaghetti.
How Cortex validates it
At plan time
The Mission plan declares the rollout strategy per change: flag, gates, metrics, kill-switch owner.
At validation
assert: risky_changes.behind_flag == trueassert: kill_switch.effect_latency < 60sassert: flags.have(owner, expiry)Assertion syntax is illustrative.
At review
The approver sees the ramp plan and the kill-switch drill result as part of the release evidence.