Back to notes

June 17, 2026 · 6 min read

Feature Flags Got Abused Into a Second Config System, a Postmortem

What started as three feature flags for a careful rollout became ninety flags, half of them permanent, functioning as an undocumented second settings system.

EngineeringPostmortem

Feature flags are supposed to be temporary — ship behind a flag, roll out gradually, remove the flag once it's fully live. On a project I inherited, the flag count had crept past ninety, and when I asked which ones were still 'in rollout' versus permanently decided, nobody on the team could tell me with confidence.

How it happened

Each individual flag addition made sense at the time. A permanent client-specific behavior difference got implemented as a flag because the flag system already existed and was faster than building proper per-client configuration. Then another one. After enough of these, the flag system had quietly become the de facto settings system for the whole platform, except it had none of the structure a real settings system would have — no schema, no validation, no single place documenting what each flag controlled or for whom.

A feature flag is a promise to clean something up later. Ninety of them is a promise nobody remembers making.

What the cleanup found

About 40% of the flags were genuinely stale — fully rolled out, the old code path unreachable, the flag just sitting there unused. Another 35% were functioning as permanent per-client config that should have been a real settings table from the start. The remaining flags were either active rollouts or legitimately ongoing experiments, the actual intended use case.

  • We removed the stale 40% first, which took a week but was low-risk — dead code paths, easy to verify.
  • The permanent-config flags got migrated into an actual client settings table with a schema, which took longer but eliminated the category of bug where a flag's state silently drifted from what anyone intended.
  • We added a 60-day flag age alert going forward, specifically so 'temporary' flags get a forced decision point instead of becoming permanent by default.
  • The lesson that stuck hardest: if a flag is being used for something that isn't a rollout or an experiment, it's a sign you're missing a real configuration system, and the flag is a symptom, not the disease.

None of the ninety flags were individually a bad decision. Collectively they were an architecture nobody designed, discovered the same way most accidental architecture is discovered — by someone new having to ask what all of it actually does.