A feature flag starts as safety and decays into debt. Each one is a second code path that only compiles in your head: a branch nobody reads, a config value nobody dares touch, an "off" state nobody has tested since the quarter it shipped. The flag you forget is not neutral — it is unvisited risk with a name like checkout_v2_final_REAL.
Full checklist with the worked example is on our ops notes. Here's the core.
1. Inventory, then three classes
One sweep: grep the codebase for flag reads, scan config and dashboards, union into one list. Then split:
- Release flags — exist to die: at 100% plus a soak period, removed.
- Ops kill-switches — permanent but owned: named person, documented off-path, drill proving it flips.
- Experiment flags — die at the decision date, written the day the flag is created.
A flag missing from the inventory is the dangerous one — nobody counts it, and uncounted risk compounds.
2. The three-field rule
Every flag carries three fields, and a flag missing any one is a defect:
- Owner — one named person, never a team. Default: whoever added the flag.
- Kill date — release flags: 100% + 14 days. Experiments: decision date. Kill-switches: quarterly review. "Temporary" with no date is a permanent flag lying about itself.
- Removal task — filed the day the flag hits 100%, with a ticket ID, into the normal backlog.
Code review enforces it in thirty seconds: a PR adding a flag without the three fields does not merge.
3. The removal ritual
- Flag at 100% for 14 days with zero flips and zero incidents → removal PR in the current sprint. Removal is the last 10% of shipping the feature, not a backlog item.
- Delete everything: the flag read, the dead path, config entry, dashboard series, tests for the removed path. Grep for stray reads — half-deleted flags are their own incident class.
- The off-path drill: flip it off in staging and watch what happens. A flag whose off-path has never been exercised is a rumor, not a safety mechanism.
- Never during a freeze; slow-rollback removals belong in a maintenance window.
4. The monthly 15-minute sweep
Flags older than 90 days with stale fields get one of two verdicts — OWN (refresh owner, date, ticket) or KILL (removal PR filed before the sweep ends). No third state. One escalation rule: any incident where a forgotten flag was a cause — that flag dies this week, and the post-mortem names the flag, its age, and its ownerless duration.
5. What flags must never gate
- Pricing and billing logic (flag flips = invoices change — that's change management, not a toggle).
- Data migrations and one-way doors (looks reversible, isn't).
- Anything an auditor must be able to explain (flags hide state from audits).
- Default-on flags with an untested off-path (a permanent code path in a safety costume).
Worked example
40-person SaaS, checkout team. 120 flags, 38 ownerless, median age 14 months. The motivating incident: a default-on release flag whose off-path broke silently in a library upgrade — when a leak forced someone to try the switch, it did nothing, and checkout ran with doubled latency for nine days. One cleanup sprint: 46 flags killed, 11 converted to drilled kill-switches, 63 total, median age 30 days. Six weeks later a bad deploy hit the same path: kill-switch flipped in 4 minutes, one-page incident report.
Metrics that matter: 100% of flags have a named owner · zero flags older than 180 days · removal lag < 2 weeks after 100% · any kill-switch flippable in < 5 minutes.
If you're cleaning this up after an incident instead of before one: the free First 30 Minutes quick-start gets the fire out, the $14 Ops Starter Kit gives small teams the full incident-response system, and the $29 Mega Bundle is all five kits.
Top comments (0)