How to clean up feature flag technical debt
Every team that uses feature flags eventually ends up with too many. 50 release flags that should have been removed months ago. 20 experiment flags from A/B tests that ended. 10 kill switches that nobody remembers why they exist.
This is the hidden cost of feature flags. Nobody talks about it until it hurts.
Here is the cleanup process we use. It works.
Step 1: list every flag and categorize
Pull a list of every flag in the system. If you’re on Flagify, it’s one command:
flagify flags list --format json > flags.json
Now sort them into four buckets:
- Release flags (temporary). Meant to go away after rollout. Most common source of debt.
- Experiment flags. For A/B tests. Should go away when the experiment ends.
- Kill switches. Permanent. Do not remove.
- Entitlement flags. Business rules (plan, role). Keep as long as the rule exists.
If a flag’s purpose is unclear, mark it “unknown” and treat it as a cleanup candidate.
Step 2: find the stale ones
A flag is stale if one of these is true:
- It has been returning the same value for all users for more than 30 days
- It was created as a temporary release flag and is older than 60 days
- It is referenced in exactly 0 places in the codebase
- Its creator has left the company and nobody owns it
The easiest signal is evaluation ratio. If a flag returns true 100% of the time for 30 days, the code path behind it is always on. You can delete the flag and keep the code.
If it returns false 100% of the time for 30 days, the code path is dead code. Delete the flag and the code.
Flagify shows evaluation stats per flag in the dashboard. Sort by “always same value” and you have your hit list.
Step 3: remove in waves
Don’t try to clean up everything at once. Pick 5 flags per sprint. Remove them properly. Move on.
For each flag:
- Check if it’s actually unused.
grep -r 'flag-name' .in the codebase. If there are no results, proceed. - If it’s always true: delete the flag from the dashboard, keep the code path, delete the conditional.
- If it’s always false: delete the flag, delete the unused code path, delete the conditional.
- Run tests. If tests pass, ship.
- Monitor. Check error rates for a day after the deploy.
Step 4: prevent the next mess
The cleanup is half the work. The other half is keeping new flags from becoming stale.
Set an expiration when you create the flag. Release flags should have a target removal date in the flag description. “Remove by April 30” is enough. Review at sprint planning.
Limit the total number of active flags. Pick a number (we use 25 per project). When you hit it, cleanup is the first task before any new flags.
Automate alerts. Most flag platforms can notify you when a flag has been at 100% for X days. Enable that.
Make cleanup part of “done.” A feature is not done when the code ships. It is done when the flag is removed.
Flag reviews in retros. Once a month, pull up the flag list. Anyone can nominate a flag for removal. Quick vote. Remove.
The actual cleanup commit
Here’s what a clean flag removal PR looks like:
- if (flagify.isEnabled('new-checkout-flow')) {
- renderNewCheckout()
- } else {
- renderLegacyCheckout()
- }
+ renderNewCheckout()
And another file:
- export function renderLegacyCheckout() {
- // 200 lines of dead code
- }
And the flag:
flagify flags delete new-checkout-flow
One PR. Three changes. No drama.
The rule: if your flag removal touches 30 files, your flag was doing too much. Split flags so each one gates one thing.
What we learned the hard way
We let our own flag count drift to 70+ in year one. About 40 of them were stale. Cleanup took two weeks of focused work.
Since then we have a standing rule: every sprint ends with at least one flag removed. It feels like busywork until you realize how much it reduces cognitive load for everyone reading the code.
If you’re starting from zero
If you have no flag cleanup process yet, start with this. Pick your 10 oldest release flags. Remove the ones that are clearly dead. You will learn the patterns in your codebase and it sets a precedent.
Flagify shows flag evaluation stats so you can identify stale flags quickly. Read feature flag best practices for naming and lifecycle rules, or see the CLI reference for how to list and delete flags in bulk.
Start for free — no credit card required.