Flag Cleanup & Technical Debt in Flagsmith
A plain-English guide to the quiet problem that grows behind every successful feature flag programme: old switches nobody remembers. Learn why flags turn into debt, how to spot the stale ones, and how to retire them safely and routinely.
Imagine opening a drawer in your kitchen and finding forty keys. Some open doors you no longer own. Some open nothing at all. A few open something important, but nobody can say which. Every time you leave the house you pick up a handful, hoping you chose well. Now imagine that drawer is part of a system serving millions of customers.
That drawer is what a feature flag setup becomes when nobody cleans it. Feature flags are wonderful when they are young. They let you release gently, test safely and switch off trouble in seconds. But every flag you create is also a promise to remember it later, and promises that nobody tracks are broken quietly. After a year, the flag list is long, the code is full of branches nobody dares to touch, and a simple change takes twice as long because no one is sure what each switch does.
You do not need to know anything about software maintenance or feature flags to follow this guide. Every new word is explained when it first appears, with an everyday comparison. By the end you will understand what flag debt is, how to measure it, how to prevent most of it, and how to retire old flags in Flagsmith safely, step by step, without frightening anyone.
1Starting From Zero: Flags and Why They Pile Up
First, a short reminder of what a flag is, and why it is so easy to create and so easy to forget.
Feature flags in one minute
A feature flag is a switch in your software that decides whether a feature is visible. Instead of hiding a new button by deleting code, you wrap the button in a check: “if the flag is on, show it.” Later you flip the flag in a dashboard and the button appears or disappears without shipping a new release. A remote config value is a close cousin. Instead of just on or off, it holds a number or some text, such as how many items to show per page.
Why creating a flag is cheap
Making a flag takes seconds. You type a name, click create, and add a check to your code. There is no meeting, no ticket and no review needed to feel safe. That ease is exactly why flags are loved. It is also the reason they multiply. Anything that is cheap to create and free to keep will be created often and kept forever, unless somebody decides otherwise.
Why removing a flag is expensive
Removing a flag is different. Someone must confirm that no code still reads it, that no customer still depends on the old behaviour, and that the flag is not secretly guarding something important. They must change code, test it, release it and then delete the flag. None of this is exciting, and none of it ships anything new. When teams are busy, cleanup slides down the list again and again.
Think of the sticky notes on a shared office fridge. Putting one up takes two seconds. Taking one down requires knowing whether it is still needed, whose it is, and whether somebody will be upset. So nobody takes them down, and eventually the fridge door is buried under yellow squares. Flags are sticky notes for your code.
The asymmetry that creates debt
Cheap to create, costly to remove, and rarely owned: that three-part combination is the root of almost every flag cleanup problem. The rest of this guide is about changing that balance, by making creation slightly more careful, and removal much easier.
Whenever you meet a new word in this guide, ask three questions: what is it, why does it exist, and what would break without it? Those answers explain most of what you need to know.
2What Technical Debt Means
A borrowed idea from money, applied to code.
The original idea
The phrase technical debt was popularised by a software engineer named Ward Cunningham. The idea is simple. When you take a shortcut in your code to ship sooner, you are borrowing time from your future self. The shortcut works today, but you will have to pay it back later, and until you do, you pay interest: everything related to that code takes a little longer, breaks a little more easily and confuses a little more people.
Not all debt is bad
Borrowing is not wrong in itself. A company that borrows to open a shop may earn far more than the interest costs. In the same way, a quick, temporary flag that lets you launch a feature this week may be exactly the right decision. The trouble begins when the debt is forgotten, when nobody knows how much exists, and when the interest quietly grows larger than the benefit ever was.
Debt versus mess
It helps to separate honest debt from plain mess. Honest debt is a deliberate choice with a plan to repay: “we added this flag to launch safely, and we will remove it by the end of next month.” Mess is the same flag with no owner, no date and no memory. The first can be managed. The second can only be discovered later, usually at a bad moment.
The work to remove it
The effort needed to delete the flag and its old code. It stays roughly the same size, or grows slowly, as long as you wait.
The ongoing slowdown
Extra reading, extra testing, extra explaining and extra risk, paid every single week the flag stays.
The chance of a nasty surprise
The probability that an old flag is flipped, deleted or misunderstood at the worst possible time.
Cleanup done on schedule
Removing flags soon after they have done their job, when the memory of why they exist is still fresh.
A small leak under a sink costs almost nothing to fix on the day it starts. Left alone, it rots the cupboard, then the floor, then the ceiling below. The leak itself never changed. The cost of ignoring it did. Flag debt behaves the same way.
Debt that nobody can see is the most dangerous kind. The first goal of this guide is not to delete anything. It is to make your flag debt visible and measurable.
3Not Every Flag Is the Same: The Four Kinds
The right cleanup plan depends entirely on what the flag was meant to do.
Teams that treat all flags alike either delete useful switches by mistake or keep useless ones forever. A better habit is to sort flags into kinds, because each kind has a different natural lifespan. A widely used way to sort them has four groups.
| Kind | Purpose | Natural lifespan | Cleanup rule |
|---|---|---|---|
| Release flag | Ship code safely, then roll out gradually | Days to weeks | Remove soon after full rollout |
| Experiment flag | Compare versions to learn which works better | Weeks, until a winner is chosen | Remove after the decision, keeping the winner |
| Operational flag, or kill switch | Turn off risky behaviour quickly during trouble | Long-lived, sometimes permanent | Review regularly, never remove casually |
| Permission or entitlement flag | Decide who gets which paid or special features | Long-lived, tied to the product | Treat as product configuration, not debt |
Release flags: the usual suspects
Most flag debt comes from release flags. They are created with a clear, short job: hide an unfinished feature until it is ready. Once the feature is fully released to everyone, the flag is dead weight, yet it remains because nobody circles back. If you remember one rule from this guide, make it this one: a release flag is born with an expiry date.
Experiment flags
An experiment compares two or more versions of something, such as two checkout designs, to learn which performs better. When the experiment ends, someone must pick the winner, make it the only version and remove the losing code and the flag. Experiments that end without a decision leave behind a flag that still splits users forever, quietly confusing later analysis.
Operational flags
A kill switch is a flag kept on hand to turn off a risky or expensive behaviour instantly, for example a feature that depends on a slow outside service. These are meant to live a long time. They are not debt in the same sense, but they still need owners and regular checks, because a kill switch nobody has tested may fail on the day it is needed.
Permission flags
Flags that decide who has access to which paid features are really product configuration wearing a flag’s clothes. They do not belong in a clean-up drive. They belong in a clearly labelled group so that nobody mistakes them for forgotten experiments.
A building has scaffolding, fire exits, door locks and signs. Scaffolding is removed when the repair ends. Fire exits stay forever. Mixing them up is dangerous in both directions: you do not want to leave scaffolding up for years, and you certainly do not want to take down the fire exits during a tidy-up.
Record the kind of every flag at the moment of creation, using a tag. Cleanup rules then become simple: temporary kinds expire, long-lived kinds are reviewed.
4The Real Costs of Leaving Flags Behind
Old flags are not harmless. They quietly tax every part of the work.
Cost one: code that is hard to read
Every flag check is a fork in the road. A reader of the code must hold both paths in mind: “if the flag is on, this happens; otherwise that happens.” With one flag, that is easy. With fifty nested flags in a single area, nobody can say what the program does without checking a dashboard, and even then the answer may differ by environment.
Cost two: a testing explosion
Each flag doubles the number of possible states of the program. Two flags give four combinations, three give eight, and ten give over a thousand. Nobody tests all of them. The untested combinations are where surprising bugs live, and they appear only for the unlucky customer whose settings happen to land on that combination.
Cost three: operational risk
A stale flag is a loaded switch with no label. Someone flips it by accident, a script changes it in bulk, or a new teammate guesses wrongly about what it does. A publicly reported trading incident from 2012 is often told as a warning: an old, long-forgotten switch was reused for a new purpose, and on one server the old code behind it was still alive. The result was a very costly failure within minutes. The details are well documented online, and the lesson is simple: dead code behind a live switch is a hazard.
Cost four: slower onboarding
New teammates must learn which flags matter and which are fossils. Without a record, they learn by asking, and the answers differ from person to person. Each confusion costs hours, and experienced engineers are interrupted again and again to explain history that should have been deleted.
Cost five: clutter in the tools
A dashboard with nine hundred flags is hard to search, slow to scan and easy to misread. Real, important flags are buried among dead ones. People stop trusting the list, and a list nobody trusts is a list nobody maintains.
Cost six: wasted effort and money
Dead flags still get evaluated, logged and carried through every release. Dead code still compiles, still gets scanned by security tools, and still needs updating when libraries change. Each of these costs is small. Together, and multiplied across years, they are significant.
A garage full of old boxes slows down every search for the one tool you need. It makes the car hard to park and the floor hard to sweep. No single box is the problem. The accumulation is. Stale flags are boxes in the garage of your code.
Do not wait for a disaster to justify cleanup. By then the debt is large, the knowledge is gone and the work is urgent. Small, regular, boring cleanup is far cheaper than heroic cleanup after an incident.
5The Life of a Flag: From Birth to Removal
Cleanup is easiest when it is planned as the last chapter of a flag’s story, not an afterthought.
flowchart LR A["Idea: ticket created"] --> B["Birth: flag created with owner, kind and expiry"] B --> C["Build: code added behind the flag"] C --> D["Rollout: staff, small group, everyone"] D --> E["Stable: flag on for all, no more changes"] E --> F["Retire: remove code, archive flag"] F --> G["Delete: flag removed from Flagsmith"]
Stage by stage
Idea
A ticket describes the feature. It includes a line that says “remove the flag” so that cleanup is part of the work from the first day.
Birth
The flag is created with a clear name, a description, an owner tag, a kind tag and a target removal date.
Build
Code is written behind the flag, with the old behaviour preserved as the safe path.
Rollout
The feature is shown to staff, then a small percentage, then everyone, with graphs watched at each step.
Stable
The flag is on for everyone and nothing is changing. This is the moment the clock for removal truly starts.
Retire
Developers delete the flag checks and the old code path, release the change, and watch for problems.
Delete
After a quiet period, the flag is archived and then deleted in Flagsmith, and the ticket is closed.
Where debt sneaks in
Almost all flag debt appears in the gap between stages five and six. The feature works, everyone is happy, attention moves to the next project, and the cleanup ticket sinks. A simple way to close the gap is to schedule the removal at the same moment the rollout reaches one hundred percent, while everyone still remembers why the flag exists.
When you finish painting a room, you peel off the masking tape the same day. Left for a month, the tape bakes onto the wall and takes the paint with it. A flag left after a rollout is masking tape that is getting harder to remove every day.
6How Flagsmith Is Organised, and Where Debt Hides
To clean thoroughly, you must know every place a flag leaves a trace.
The containers
Flagsmith organises everything in layers. An organisation is your company account. A project is usually one product. An environment is one stage of that product, such as development, staging or production. A feature is the definition of a flag, shared across the whole project. A feature state is the value of that feature inside one environment.
The traces a flag leaves
Deleting a flag in the dashboard removes only one of its traces. A thorough cleanup considers all of them.
Flag checks
The conditions that read the flag, plus the old branch of code that runs when the flag is off. This is usually the largest piece of debt.
Default values
The fallback entries kept in your SDK setup. They linger quietly after the flag is gone.
Test scenarios
Tests that switch the flag on and off. They must be simplified when only one path remains.
Feature and feature states
The flag itself, with a separate value in every environment.
Segment overrides
Special values for groups of users, which keep influencing decisions until removed with the flag.
Identity overrides
Special values for individual users, easy to forget and surprising to rediscover.
Integrations and webhooks
Dashboards, alerts and automations that mention the flag by name.
Documents and tickets
Runbooks, wiki pages and tickets that tell people the flag exists.
Environments drift
A flag can be fully on in production, half on in staging and off in development. When it is time to remove it, each environment must be considered. If the flag still has different values in different places, you must decide which value represents the truth before deleting it, because the code you keep must match the behaviour you want everywhere.
Before removing a flag, list all its traces in a short checklist. A flag that has been fully removed from code but still has identity overrides in Flagsmith is half-cleaned and will confuse the next person to find it.
7Prevention: Starting Every Flag With the End in Mind
The cheapest cleanup is the cleanup you planned on the day the flag was created.
The birth certificate
Every new flag should be created with a small set of information, a sort of birth certificate. It takes one minute to fill in and saves hours later.
| Field | Example | Why it helps |
|---|---|---|
| Name | checkout_new_payment_form | Says what area and what change, so graphs and logs explain themselves |
| Description | Shows the redesigned payment form to eligible users | Gives future readers the reason, not just the label |
| Owner tag | team-payments | Tells everyone whom to ask |
| Kind tag | release | Decides whether the flag should expire |
| Removal date | Within thirty days of full rollout | Turns a vague intention into a visible deadline |
| Ticket link | Link to the work item | Connects the flag to its story and its cleanup task |
Naming that lasts
Good names are the cheapest form of documentation. Begin with the product area, describe the change and avoid names that depend on who asked for it or when it was made. Avoid vague words such as test, new and temp, which age badly. Use the same word separator everywhere so searches work. A name like checkout_new_payment_form will still make sense in two years. A name like newflag2 will not make sense in two weeks.
Tags as the glue
Flagsmith lets you attach tags to flags. Tags are the easiest way to record owner and kind, and they make filtering simple: “show me every release flag owned by the payments team.” If tags are applied consistently from the start, most of the reports and automations later in this guide become simple to build.
Make the removal task part of the plan
The most effective prevention habit is to create the removal task at the same moment as the flag. Put “remove flag and old code” into the original ticket as its own checklist item, or open a linked ticket with a due date. A task that exists from the beginning is far more likely to be done than a good intention.
A responsible camper packs a rubbish bag with the tent. The bag is not an afterthought. It is part of the packing list, so leaving no trace is simply what happens. A removal task created with the flag is the rubbish bag in your pack.
Do not rely on memory or goodwill. Teams change, priorities shift, and the person who created a flag may have left. Write the owner and the expiry where everyone can see them.
8Finding the Stale Flags: Detection
Before you can clean, you must know what is dirty.
What “stale” means
A stale flag is one that has stopped doing useful work. Its value no longer changes, or its decision no longer matters, but it still sits in the code and the dashboard. Staleness has several faces, and good detection looks for each.
Old and unchanged
The flag was created long ago and has not been edited for months. Temporary flags in this state are prime suspects.
Same value everywhere
The flag is on, or off, in every environment with no segment rules. A switch that never differs is not switching anything.
Never read
Usage reports show no evaluations for a long time. Nobody is asking the flag anything, so the code may already be gone.
No owner
Nobody claims it. Ownerless flags are almost always forgotten ones.
Past its removal date
A flag that has outlived its own deadline is the clearest candidate of all.
Closed ticket
The linked work item is finished, yet the flag remains.
Tools you can use
Flagsmith offers several features that help with detection, though the exact names and availability differ by version and plan, so check your own account. Typical helpers include tags and the ability to mark a flag as stale, an archive option that hides retired flags from everyday lists, flag usage reporting from SDKs, an audit log of every change, and integrations that link flags to code hosting and issues. Some versions can also scan code repositories to show where a flag is referenced, which directly answers the question “is this still used anywhere?”
Use the API for custom reports
For anything the dashboard does not offer, the REST API lets you read every flag with its tags, creation date and state across environments. A small script can build a report of every release flag older than ninety days that is identical in all environments and has no segment rules. That single list is often the most productive cleanup backlog a team can have.
Cross-check before you trust a signal
No single signal proves a flag is dead. A flag that is never read might guard a rarely used report. A flag that has not changed for a year might be a valuable kill switch. Treat the signals as a way to build a short list, then confirm each flag with a person and with a code search before acting.
A librarian deciding which books to retire looks at when each was last borrowed, whether newer editions exist and whether anyone has asked for it recently. None of these facts alone settles the matter, but together they make a good shortlist, which the librarian then checks by hand.
9Measuring Flag Debt
What gets measured gets managed. A handful of simple numbers tells you almost everything.
Five numbers worth tracking
| Measure | What it tells you | Healthy direction |
|---|---|---|
| Total number of flags | The overall size of the problem | Stable or slowly falling |
| Share of flags older than a set age | How much of the list is likely stale | Falling |
| Share of flags with an owner tag | How well responsibility is recorded | Approaching one hundred percent |
| Flags created versus flags removed each month | Whether debt is growing or shrinking | Removed at least equals created |
| Flags past their removal date | How well deadlines are honoured | Near zero |
The most important ratio
If you track only one thing, track the monthly balance between flags created and flags removed. If you create thirty and remove ten, you gain twenty flags of debt every month, and the list will double within a year. If you remove as many as you create, the list stays steady however busy you are. This single ratio turns a vague worry into a clear target.
flowchart LR
C["Flags created each month"] --> B{"Compare"}
R["Flags removed each month"] --> B
B -->|"Created greater than removed"| G["Debt growing: schedule cleanup"]
B -->|"About equal"| S["Debt stable: keep the habit"]
B -->|"Removed greater than created"| D["Debt shrinking: good progress"]
Put the numbers where people can see them
Numbers hidden in a spreadsheet change nothing. Publish them on a team page, include them in a monthly review, and celebrate improvements. A simple chart that shows the flag count by month is enough to start conversations. When the line rises steadily, people notice, and noticing is the first step of repayment.
Choose targets you can reach. “No flags older than ninety days” may be impossible on day one. “Cut the number past their removal date in half this quarter” is achievable, visible and motivating.
10Deciding What to Remove: A Triage Method
Not every old flag should go, and not every flag should go at once.
Sort candidates into four boxes
Once you have a shortlist, sort each flag into one of four boxes. This takes a few minutes per flag and prevents most mistakes.
Remove now
Fully rolled out, same value everywhere, owner agrees, and no reason to keep a way back. These are the easy wins.
Remove after a short wait
Recently completed. Keep the flag a little longer as a safety net, with a firm date to remove it.
Keep, but label properly
Genuinely long-lived switches such as kill switches and entitlements. Tag them as permanent, assign owners and schedule reviews.
Investigate first
Nobody knows what it does. Find out before touching it, by reading code, checking usage and asking around.
Questions that decide the box
- Is the flag on or off for everyone, in every environment? If yes, one path of code is dead.
- Which path is dead? If the flag is on for everyone, the “off” code can go. If it is off for everyone, the feature was abandoned and the “on” code can go.
- Is there any reason to switch it back? A recently launched feature may still need an emergency way back.
- Does anything else depend on it? Other flags, reports, partners or scheduled jobs may read it.
- Who owns it, and do they agree? If the owner is unknown, escalate before acting.
Ranking by value and safety
Start with flags that are easy to remove and costly to keep: old, fully rolled out, in busy parts of the code. Leave the tricky ones for later, once the team has built confidence and routines. Quick, safe wins create momentum, and momentum is what makes cleanup a habit instead of a one-off campaign.
When clearing a loft, you first throw away the obvious rubbish, then set aside things to donate, then label boxes to keep, and only then spend time on the mystery boxes. Starting with the mystery boxes would exhaust you before making any progress.
Never delete a flag just because it looks old. Old and unused are different things. Confirm with usage data, code search and the owner before removing anything from production.
11The Safe Removal Process, Step by Step
The order of operations matters. Removing things in the wrong order is how outages happen.
sequenceDiagram participant O as Owner participant C as Code participant F as Flagsmith participant M as Monitoring O->>F: Confirm final value in every environment O->>C: Remove flag checks and the dead code path C->>C: Update tests and default values C->>M: Release and watch graphs M-->>O: Quiet period passes with no problems O->>F: Archive the flag F-->>O: Hidden from everyday lists, easy to restore O->>F: Delete the flag after a final wait
The steps in detail
Confirm the final truth
Check the flag’s value in every environment and every segment rule. Decide which behaviour is the winner and make sure it is what you want everywhere.
Search for every use
Search all code repositories, including mobile apps, web code, backend services and scripts. Remember that old mobile versions still read the flag.
Remove the checks and the dead path
Keep the winning behaviour as plain code. Delete the losing branch and any helper functions only it used.
Tidy tests and defaults
Simplify tests that toggled the flag, and remove its entry from default values and documentation.
Release and watch
Ship the change in a normal release. Watch error rates and key business graphs, just as you would for any change.
Wait through a quiet period
Keep the flag in Flagsmith while you wait. Long enough to cover one full business cycle, such as a week or month-end, is wise.
Archive
Archiving hides the flag from everyday lists but keeps it available for restoration if something unexpected appears.
Delete and close out
After a further wait, delete the flag, along with its overrides, and close the ticket with a short note of what was done.
Why code comes before the dashboard
A common mistake is deleting the flag in the dashboard first because it is the quickest step. If any code still reads the flag, that code now gets a missing value and falls back to its default, which may silently flip behaviour for real users. Removing the code first means the flag is already unnecessary when it disappears.
Why archive before delete
Archiving is a gentle step. If a forgotten report or an old app version still depends on the flag, the failure will appear, you will notice, and you can restore the flag within seconds. Deleting is permanent, so it deserves a pause and a final check.
Before demolishing a wall, a builder confirms it carries no load, switches off the wiring, removes fixtures, and only then knocks it down. Nobody starts with the hammer. Removing a flag is demolishing a wall inside a live building.
12The Code Side: Removing Flag Checks Cleanly
Most of the cleanup effort lives in code, not in the dashboard.
What a flag check looks like in spirit
In plain terms, a flag check is a fork: “if the flag is on, do the new thing, otherwise do the old thing.” Removal means choosing the winner of that fork, keeping its code, and deleting the other path together with the fork itself. When the flag is fully on, you keep the new path. When the flag was abandoned and is off, you keep the old path.
Common shapes of flag use
Simple branch
One check, two paths. The easiest to remove: keep one path, delete the other.
Nested checks
A flag inside another flag’s branch. Remove the inner ones first, then the outer, and test after each step.
Checks scattered across files
The same flag read in many places. A thorough code search is essential, and a single list of usages helps.
Flag value passed around
The flag is read once and the result travels through functions. Follow the value to every place it changes behaviour.
Config values
A text or number flag. Replace the lookup with a fixed value or a normal setting in your own configuration.
Multivariate flags
Several variations of a feature. Keep the winning variation and remove all the rest, with their code.
Habits that make removal safe
- Isolate flag checks. Keep each flag read in as few places as possible, ideally one decision point, so removal touches little code.
- Prefer small, separate changes. Remove one flag per change, so a problem points at one cause.
- Let tests lead. Make sure the winning path is well covered by tests before deleting the losing path.
- Remove helpers too. Functions, styles and assets used only by the dead path should go with it.
- Let tools help. Linters and static analysis can flag unreachable code after the check is removed.
Removing a railway junction means choosing which track to keep, lifting the other one and the switch that joined them, and updating the signal diagram. If you lift the track but leave the signals, the next driver is confused. The code that decided and the code that was decided between must both go.
Write flag checks so that the old behaviour is a clearly separate block. When the day of removal comes, deleting a clearly marked block is far less risky than untangling a mixed one.
13The Flagsmith Side: Archive, Delete, Overrides and Environments
What to do in the dashboard once the code is clean.
Archiving
Flagsmith lets you archive a flag. An archived flag is hidden from normal lists, which reduces clutter, but it is not destroyed. Archiving is ideal as a holding area: it signals “this is retired” to everyone, while keeping the option of bringing it back. The exact behaviour of archived flags in SDK responses can differ, so confirm in the documentation for your version, and test with a non-production flag first.
Deleting
Deleting removes the flag and its states permanently. Its history in the audit log remains, which is valuable: months later, someone can still learn when and by whom a flag was removed. Delete only after the quiet period has passed, and make sure the owner has signed off.
Overrides: the hidden leftovers
Segment overrides give a flag special values for groups of users. Identity overrides give special values to individual users. Both are easy to forget. When a flag is deleted, its overrides disappear with it, but while the flag is alive they continue to influence results. Before retiring a flag, review its overrides, because they may reveal users or groups that still depend on the old behaviour.
Environments
Check every environment. A flag may be long finished in production but still used in a staging test or an old demo environment. If you remove it everywhere at once, those places may break. Either update them in advance or accept that they will use defaults and fix them as they appear.
Segments left behind
Segments are reusable groups, such as “beta testers.” After removing a flag, the segment may now be unused. Review segments too, since an old segment that no flag uses is a small piece of debt of its own. Take care, though: a segment might be used by other flags, so check before deleting.
| Item | Question to ask | Action |
|---|---|---|
| Feature | Is any code still reading it? | Archive, wait, then delete |
| Feature states | Do all environments agree on the winner? | Confirm before deleting |
| Segment overrides | Does any group still depend on special behaviour? | Review, then let them go with the flag |
| Identity overrides | Are any real users specially treated? | Check with the owner before deleting |
| Segments | Is any other flag using this group? | Delete only if unused everywhere |
| Tags | Are they still meaningful? | Tidy occasionally |
Deleting is not undoable in the way archiving is. If you are unsure, archive and wait. Waiting costs a little clutter. A wrong deletion can cost an outage.
14Special Case: Experiments and Multivariate Flags
Flags with several versions need an extra step: choosing the winner.
Why experiments are tricky
A normal release flag has two states. An experiment has several variations, each shown to a share of users. When it ends, you must decide what happens to every user who was in a variation. The winner becomes the only behaviour. The losers are removed. Skipping the decision leaves users permanently split into groups nobody is studying.
A clean ending for an experiment
Stop collecting
Decide in advance how long the experiment runs and how many users it needs, then stop when that point is reached.
Record the result
Write down what was tested, what was learned and which variation won, in a place the whole team can find.
Roll the winner to everyone
Move one hundred percent of users to the winning variation and confirm the graphs stay healthy.
Remove the losers
Delete the code, styles and assets for the losing variations.
Retire the flag
Follow the normal archive and delete process, and tell the analytics team so old charts remain understandable.
Keep the analytics story intact
If your analytics tools received flag states as user properties, those properties will stop updating when the flag is removed. Make a note in the analysis documents, so that someone studying data next year understands why the property disappears on a certain date, and which variation became the default from then on.
A taste test at a market ends when the stall owner picks a recipe, writes it on the menu and takes the other samples off the table. Leaving every sample out forever would make it impossible to know what the shop actually sells.
Put the experiment’s end date and decision owner into the flag description at creation. An experiment with a named owner and a date finishes. One without drifts on indefinitely.
15Special Case: Mobile Apps and Old Versions
On phones, old code never really dies.
The long tail of app versions
On a server, you control when new code runs. On a phone, users update when they feel like it. Some never do. This means that for months or years, versions of your app that still read an old flag may keep running on real devices. If you delete the flag the moment your newest version stops using it, those old versions may behave unpredictably.
What happens to old versions
When an old app asks for a flag that no longer exists, the SDK returns nothing, and the app falls back to its built-in default. If the default was chosen sensibly, the old app simply shows its old behaviour. If the default is the opposite of what the flag had been saying, those users suddenly see the feature disappear or appear, which can be confusing or even harmful.
A safe approach
- Check how many users run old versions. Use analytics to see which versions are still active.
- Keep the flag until old versions fade. If a meaningful number of users run a version that reads the flag, keep the flag alive in its final state until they upgrade or you retire support.
- Choose defaults that match the final state. For future versions, set the default to the winning behaviour so removal changes nothing.
- Use a version trait. Send the app version as a trait, so you can target or exclude old versions precisely.
- Consider forced upgrades. If very old versions block cleanup, a gentle upgrade prompt can help.
| Situation | Risk of deleting now | Better action |
|---|---|---|
| Only the latest app version reads the flag | Low | Follow the normal removal process |
| Older versions with many users still read it | High | Keep the flag in its final state until they fade |
| Older versions have a default opposite to the final state | High | Keep the flag, or wait for those versions to retire |
| Web code only, always latest | Low | Remove after a normal quiet period |
A city can replace all its road signs in a weekend, but it cannot replace the printed maps people already carry in their glove boxes. Old maps keep sending drivers down roads you have changed. Old app versions are the old maps in the glove box.
16Automating the Boring Parts
Cleanup that depends on remembering will fail. Cleanup that machines remind you about will not.
What can be automated
Monthly stale-flag report
A script reads all flags through the API and lists those past their removal date, ownerless, or identical everywhere, grouped by owning team.
Reminders to owners
The report posts a polite message to each team’s chat channel: “These four flags are past their removal date. Are they still needed?”
Rules at creation
A pipeline check refuses to create a release flag without an owner tag and a removal date.
Automatic stale labels
A job marks suspicious flags with a “cleanup-candidate” tag, making them easy to find and discuss.
Code search
A scheduled search lists flags that no longer appear in any repository, which is strong evidence of a dead flag.
Snapshots
A nightly export saves the state of all flags, so you can compare, restore or audit later.
flowchart TD S["Scheduled job each week"] --> L["Read all flags through the REST API"] L --> F["Filter: past removal date, no owner, same value everywhere"] F --> T["Tag cleanup candidates"] T --> R["Build report grouped by team"] R --> N["Post to team chat channels"] N --> H["Owners decide: remove, extend or mark permanent"] H --> U["Record decision in flag description"]
Automation advises, humans decide
Resist the urge to delete automatically. A script that archives or deletes flags on its own will eventually remove something important. Let automation find candidates, label them and nag owners, while people make the final decision. If you do automate archiving, restrict it to flags that meet strict, well-tested conditions, and always run a dry run first.
Use least privilege for cleanup robots
A reporting script needs only read access. A tagging script needs permission to edit tags. A script that archives needs a little more. Give each job its own named key with only the permissions it needs, so the audit log shows exactly which robot did what, and a mistake cannot cause more damage than its role allows.
Make scripts safe to run twice. They should set a desired state, such as “tagged as candidate,” never toggle something on and off. Reruns after a crash must do no harm.
17Organising the People Side: Ownership and Rituals
Technical debt is a people problem wearing technical clothes.
Who owns cleanup?
The creator of a flag should own its removal. This is the simplest and most effective rule. It keeps responsibility close to knowledge, since the person who made the flag knows best why it exists. When the creator leaves or changes teams, ownership passes to the team, not to the void. That is why the owner tag names a team, not just a person.
Rituals that make cleanup normal
Five-minute flag glance
During a regular team meeting, look at the list of flags past their removal date. If it is empty, celebrate. If not, assign each one.
Cleanup in the definition of done
A feature is not finished until its flag is removed, or the removal is scheduled with a date.
Debt report review
Look at the created-versus-removed balance and the age profile, and discuss trends.
Cleanup day
A shared, time-boxed session where teams retire their candidates together, with snacks and recognition.
Make removal respected work
Cleanup rarely wins praise, because nothing visible ships. Change that. Mention flag removals in team updates. Count them in planning. Treat a deletion that makes a file simpler as an achievement. When removal is respected, it gets done. When it is treated as a chore for later, it never is.
Budget some time for it
Reserve a small, steady share of each team’s time, such as a few percent, for cleanup and maintenance. This keeps debt from compounding and avoids the awkward bargaining over every single cleanup task. A modest regular allowance beats a large occasional campaign.
A restaurant kitchen is cleaned a little at every shift and deep-cleaned on a schedule. A kitchen cleaned only when the inspector visits is always one bad day from closure. Regular, small, shared cleaning is the cheapest way to stay safe.
Make the first cleanup day easy and rewarding. Pick fifteen obvious flags, finish them in an afternoon, and share the results. Early success builds trust in the process.
18Security, Permissions and Audit During Cleanup
Cleanup changes production, so it deserves the same care as any other change.
Permissions
Not everyone should be able to delete flags. A sensible arrangement lets many engineers view flags, a smaller group archive and delete them, and reserves administrative actions for a few trusted people. This follows the principle of least privilege: each person and each robot gets only the access the job requires.
Approval for risky removals
For flags that touch critical paths such as payments or login, require a second person to review the removal plan. Some Flagsmith plans offer change approval workflows. Where they are not available, a pull request on the code change and a short checklist in the ticket achieve the same discipline.
The audit log as your safety record
Every change, including archive and delete, is written to the audit log with who made it and when. This gives you a trustworthy history for incident reviews and for audits. It only works if identities are meaningful, so avoid shared logins and give each automation its own named key.
Keys and secrets
Cleanup scripts use powerful credentials. Keep them in a secrets manager, never in repositories or chat messages, rotate them on a schedule, and revoke them when a script is retired. A forgotten cleanup key with delete permission is a hazard of its own.
| Risk | Example | Simple defence |
|---|---|---|
| Wrong deletion | A kill switch removed because it looked unused | Kind tags, owner approval, archive before delete |
| Over-powerful script | Reporting job with delete permission | Least-privilege keys per job |
| No accountability | Shared login hides who deleted a flag | Personal accounts and named keys |
| Leaked key | Cleanup key committed to a repository | Secrets manager, scanning, quick rotation |
| Silent breakage | Old app versions lose a flag they relied on | Check version usage, keep final-state flags |
In a hospital, throwing away old medicine is done by authorised staff, logged, and checked against records. Nobody doubts the nurses. The routine simply ensures that an expired bottle goes in the bin and an important one does not.
19Monitoring and Watching After a Removal
A removal is a change, and every change deserves a few minutes of attention afterwards.
What to watch
- Error rates in the services touched by the change.
- Key business graphs such as sign-ups, orders or successful payments.
- Fallback and default usage in SDK logs, which can reveal code that still reads the removed flag.
- Support tickets and user reports in the day or two following.
- Old app version behaviour, if mobile clients are involved.
Use markers on dashboards
Flagsmith integrations can push flag change events to monitoring tools, so that archive and delete actions appear as markers on your graphs. If a metric changes right after a marker, you know where to look first. Make sure cleanup robots have clear names so the markers explain themselves.
A short watch routine
Minutes after release
Check error rates and the key graphs for anything unusual.
Hours after release
Look at support channels and logs for missing-flag warnings.
Days after release
Confirm the quiet period passed with no problems before archiving.
Weeks after archiving
Confirm nothing tried to restore or read the flag, then delete it.
Know how to go back
Decide your way back before you start. If the code removal causes trouble, the usual path is to revert the release. If the flag was archived, unarchive it. Because flags are switches, a restored flag with its final value is usually enough to bring the old behaviour back quickly while you investigate calmly.
Write the reversal steps in the ticket before starting. A rollback plan written in a calm moment is worth ten written during an incident.
20Design Patterns and Anti-Patterns
Habits that keep flag debt low, and habits that quietly build it.
Patterns worth copying
Flag with an expiry
Every temporary flag is born with an owner, a kind and a removal date.
Cleanup in the definition of done
A feature is not complete until its flag is removed or the removal is scheduled.
Single decision point
Each flag is read in one place in code, so removal touches little.
Created-versus-removed balance
The team watches the monthly balance and keeps it level or falling.
Archive, wait, delete
A gentle retirement path that allows a quick way back.
Automated nudges
Scripts find candidates and remind owners, and people make the decisions.
Advantages and trade-offs of regular cleanup
Advantages
- Simpler code that new teammates understand quickly.
- Fewer combinations to test and fewer hidden bugs.
- Lower operational risk from forgotten switches.
- A clean, trusted flag list in the dashboard.
- Faster changes, because less history must be understood first.
Trade-offs
- Time spent that ships no visible feature.
- A small risk with every removal, managed by process.
- Need for tags, owners and reports, which take upkeep.
- Occasional disagreement about whether a flag is still needed.
- Extra care required for mobile apps and old versions.
Anti-patterns to avoid
What people do
They create flags with vague names and no owner, intending to “sort it out later.”
Why it hurts
Later never comes. Months afterwards, nobody can tell what the flag does or who may remove it, so it stays forever.
Better approach
Require a clear name, a description, an owner tag and a removal date at creation.
What people do
They delete flags in the dashboard first because it is quick, before removing the code.
Why it hurts
Code still reading the flag now receives a missing value and silently falls back to a default, which may change behaviour for real users.
Better approach
Remove code first, release, wait, archive, and only then delete.
What people do
They reuse an old flag name for a new purpose to save time.
Why it hurts
Old code, old overrides and old app versions may still react to the name, producing behaviour nobody intended. This pattern is behind some of the best-known flag-related incidents.
Better approach
Always create a fresh flag with a new name, and fully retire the old one.
What people do
They run a one-time heroic cleanup, then go back to creating flags carelessly.
Why it hurts
The list is clean for a month and then grows again. Effort is wasted because the causes were never addressed.
Better approach
Fix creation habits and add small, regular rituals so the list stays clean.
What people do
They use permanent flags to hide permanent differences, such as customer-specific behaviour, without calling them configuration.
Why it hurts
These flags look like debt but cannot be removed, so they get deleted by mistake or ignored forever, and nobody knows which is which.
Better approach
Tag long-lived flags as permanent, give them owners, and review them on a schedule.
21Best Practices and Common Mistakes
A practical checklist drawn from everything so far.
Do these
- Tag every flag with an owner and a kind when it is created.
- Give temporary flags a removal date and a linked ticket.
- Schedule removal at the moment of full rollout, while memory is fresh.
- Measure the created-versus-removed balance every month.
- Remove code first, then archive, wait, and delete.
- Review overrides and environments before retiring a flag.
- Handle old mobile versions deliberately.
- Let automation find candidates and let people decide.
Common mistakes and quick cures
| Mistake | What you see | Cure |
|---|---|---|
| No owner tag | Hundreds of flags nobody claims | Make the owner tag mandatory at creation |
| No removal date | Temporary flags live for years | Add a date and a linked cleanup task |
| Deleting before removing code | Surprise behaviour changes after deletion | Follow the code-first order |
| Forgetting identity overrides | A few users are treated oddly long after cleanup | Review overrides before retiring the flag |
| Treating kill switches as clutter | The emergency switch is gone when needed | Tag permanent flags and review them separately |
| Ignoring old app versions | Complaints from users on older releases | Check version usage before deleting |
| Cleanup only in campaigns | The list grows back within months | Build small weekly and monthly habits |
22A Worked Example: A Streaming Company Pays Down Its Flag Debt
A made-up company shows how the pieces fit together.
The story below is hypothetical. Imagine a video streaming company called Blue Harbor, with a mobile app, a web player and ten backend services. After four years, Flagsmith shows 1,100 flags. Nobody can say how many matter. A new engineering manager decides to bring order.
Step one: make the debt visible
An engineer writes a read-only report using the Flagsmith API. It lists every flag with its age, tags, values in each environment and whether it has segment rules. The shocking numbers: 640 flags have no owner tag, 520 are older than a year, and 410 have the same value in every environment.
Step two: agree on kinds and rules
The teams agree on four kinds: release, experiment, operational and permission. They agree that every new flag needs an owner tag, a kind tag and, for temporary kinds, a removal date. A pipeline check enforces the rule from that day on.
Step three: triage the easy wins
The report is filtered to release flags, older than a year, identical everywhere, with no segment rules. That produces 260 candidates. A weekly job tags them “cleanup-candidate” and posts lists to each team’s channel, asking owners to confirm.
Step four: investigate the mysteries
For 180 flags with no owner, a code search shows that 120 are not referenced anywhere in any repository. The platform team archives those after a short announcement, keeping them restorable for a month. The other 60 are still referenced and go into an investigation box.
Step five: careful with mobile
Analytics show that 8 percent of mobile users still run versions from two years ago. Flags read by those versions are kept in their final state, and tagged “keep until version retired.” The team schedules a gentle upgrade prompt for those users.
Step six: remove in small batches
Developers remove flag checks in small changes, one flag per change, with tests. After each release, graphs are watched. One removal reveals a rarely used report that still read a flag. The flag is restored from archive in seconds, tagged as long-lived, and given an owner.
Step seven: delete and learn
After a month without surprises, the archived flags are deleted. The audit log records every deletion against a named cleanup key. The team writes a short note about what they learned, including the rarely used report.
Step eight: make it a habit
The team sets a rule that flags created each month must be matched by flags removed. A five-minute weekly glance at overdue flags, a monthly debt review and a quarterly cleanup day keep the list steady. Within six months the total falls from 1,100 to 380, and every remaining flag has an owner.
What made this smooth
Nothing needed heroics. The team made debt visible, agreed on simple rules, let machines find candidates and humans decide, protected old app versions, and watched after every removal. Each small habit covered a different risk, and together they turned an intimidating mess into a routine chore.
23The Same Idea in the Wider World
Every growing system faces the same quiet decay. Learning from other fields makes the lesson stick.
Flag debt is one example of a much older pattern: things that are easy to add and hard to remove accumulate until they hurt. The examples below describe publicly known practices in general terms, not any company’s private systems.
Dead code
Code that can never run still costs reading time and testing effort. Engineering teams use tools and reviews to find and remove it regularly.
Deprecated features
Large platforms announce retirements long in advance, give timelines, and keep old versions alive for a while, just as old app versions should be treated here.
Unused cloud resources
Teams regularly hunt for forgotten servers, disks and accounts that still cost money and expand the attack surface.
Stale accounts and keys
Security programmes review old accounts and credentials, because forgotten access is a classic route for trouble.
Retention policies
Organisations delete data after a set period instead of keeping everything forever, reducing both cost and risk.
Subscriptions
Many people discover old subscriptions they forgot. A periodic review is the cure, and the same is true for flags.
The shared pattern
Across all of these, the same few habits keep appearing. Record who owns each thing. Give temporary things an end date. Measure how much exists. Review on a schedule. Retire gently, with a way back. Make removal respected work. Teams that follow these habits in one area find it easy to apply them in another.
A well-run library does not keep every book forever, nor does it discard books at random. It records what it owns, checks how often each is borrowed, moves rarely used books to storage, and withdraws those that are truly outdated. Flag management follows the same quiet librarian’s logic.
Lessons you can reuse
- Plan the end of a thing on the day it begins.
- Keep an inventory with owners.
- Prefer small, regular tidying over occasional crisis cleaning.
- Retire in stages so mistakes can be undone.
- Measure the trend, not just the total.
24Limits: What Cleanup Cannot Do
Knowing the limits of any practice is as valuable as knowing its strengths.
It cannot replace good creation habits
No amount of cleanup will keep up with careless creation. If flags keep appearing without owners and dates, you will always be digging out. Prevention and cleanup are two halves of one habit.
It cannot be fully automated
Machines can find candidates, but only people can judge whether a flag still matters. Business context, customer promises and upcoming plans live in human heads. Treat automation as a flashlight, not a bulldozer.
It cannot remove risk entirely
Every change carries some risk, including removal. Process reduces the risk but does not erase it. That is why small steps, quiet periods, watching and rollback plans matter.
It cannot fix poorly structured code
If flag checks are scattered across hundreds of files, removal will be slow however well planned. Cleanup reveals structural problems, and fixing them is a separate, longer task. Improve how flags are read in code so future removals are easier.
It is not a substitute for deleting features that should never have shipped
Sometimes a flag marks a feature that is genuinely abandoned. The right answer is to remove the feature entirely, not to keep a switch that can never matter. Product decisions and flag decisions should be made together.
| You want to | Do | Do not |
|---|---|---|
| Stop debt from growing | Fix creation habits with owners and dates | Rely on occasional campaigns |
| Find stale flags | Combine usage data, age, owners and code search | Trust a single signal |
| Retire a flag | Code first, then archive, wait and delete | Delete in the dashboard first |
| Handle kill switches | Tag as permanent and review regularly | Treat as clutter |
| Speed up cleanup | Automate reports and reminders | Automate deletion without review |
If a cleanup task feels impossible, shrink it. One flag, one change, one release. Small steps are how every large pile eventually disappears.
25A Ninety-Day Plan, a Runbook and a Cheat Sheet
Three practical tools to keep beside your team’s notes.
Part one: a ninety-day plan
See the debt
Build a read-only report of all flags with age, tags and values. Agree on kinds and owner tags. Make owner and kind mandatory for new flags. Publish the baseline numbers.
Harvest the easy wins
Triage release flags that are old and identical everywhere. Remove the checks in small changes, archive after a quiet period, and delete. Start the weekly glance at overdue flags.
Make it automatic
Schedule weekly reports and owner nudges, add pipeline rules, set the created-versus-removed target, and hold the first quarterly cleanup day.
Part two: a removal runbook
A runbook is a short, step-by-step guide that a tired person can follow. Here is one for retiring a single flag.
Confirm kind and owner
Make sure the flag is a temporary kind and the owner agrees to the removal.
Confirm final value everywhere
Check every environment, segment rule and identity override. Decide the winning behaviour.
Search all code
Include mobile, web, backend, scripts and tests. Check which app versions read the flag.
Remove code and tidy
Keep the winning path, delete the rest, simplify tests and remove the default value.
Release and watch
Ship normally and watch errors and key graphs.
Archive after the quiet period
Hide the flag from lists while keeping it restorable.
Delete and record
Delete the flag, close the ticket and write a one-line note of what was done.
Part three: a one-page cheat sheet
- Tag at birth. Owner, kind and removal date, always.
- Plan the end. The removal task is created with the flag.
- Measure the balance. Created versus removed, every month.
- Find by many signals. Age, sameness, usage, owners, code search.
- Triage into four boxes. Remove now, remove soon, keep and label, investigate.
- Code first. Then release, archive, wait and delete.
- Mind the leftovers. Overrides, segments, environments and old app versions.
- Automate the nudges. Humans make the decisions.
- Protect kill switches. Label them permanent and review them.
- Keep it small and regular. A little every week beats a campaign every year.
Pin this list beside your team’s runbook. New joiners can read it in two minutes, and experienced engineers will find that it settles most arguments quickly. Good habits around cleanup are what turn a fast-growing flag programme into a lasting asset instead of a slowly collapsing pile.
One last piece of advice concerns patience. Nobody clears four years of debt in a week. Begin with the easy wins, build routines, and let the numbers show your progress. Teams that clean gradually and consistently end up with simpler, safer systems than teams that wait for a perfect moment, because every removal is justified by a real flag they have already examined.
26A Plain-English Glossary
Quick definitions of the words used in this guide.
Feature flag
A switch in software that decides whether a feature is visible.
Technical debt
Extra future work caused by shortcuts or neglect, with ongoing interest in the form of slowdowns and risk.
Flag debt
The build-up of old, unneeded flags that make code harder to understand and test.
Stale flag
A flag that has stopped doing useful work but still sits in code and dashboard.
Release flag
A temporary flag used to ship and roll out a feature safely.
Experiment flag
A flag that splits users to compare versions until a winner is chosen.
Kill switch
A long-lived flag kept to turn off risky behaviour quickly.
Permission flag
A flag that decides who gets which paid or special features.
Environment
One stage of a project, such as development, staging or production.
Segment override
A special flag value for a group of users.
Identity override
A special flag value for one individual user.
Tag
A label attached to a flag, such as its owner or kind, used for finding and filtering.
Archive
Hiding a flag from everyday lists while keeping it restorable.
Audit log
The official diary of who changed what and when.
Least privilege
Giving each person or robot only the access the job needs.
Runbook
A short, step-by-step guide for a routine or an emergency task.
Idempotent
Safe to repeat: doing it twice has the same effect as doing it once.
Dead code
Code that can never run, but still has to be read, tested and maintained.
27Making the Business Case for Cleanup
Cleanup competes with new features for time. Here is how to win that argument fairly.
Speak the language of cost and risk
Managers rarely respond to “the code is messy.” They respond to cost, speed and risk. Translate flag debt into those terms. Cost: how many engineer-hours are spent each month working around old flags, explaining them to newcomers, or testing combinations that should not exist. Speed: how much longer changes take in areas crowded with flags. Risk: how many critical paths contain switches nobody understands.
Estimating the interest
You do not need exact figures. A rough estimate is enough to start a conversation. Ask a few engineers how many minutes a week they lose to flag confusion, multiply by the number of people, and convert to hours per month. Then compare that with the hours needed to remove the oldest hundred flags. Very often the one-time cost of removal is repaid within a few months.
| Item | Example estimate | How to gather it |
|---|---|---|
| Time lost per engineer per week | About 30 minutes | Short anonymous survey |
| Engineers affected | 40 | Team size in flag-heavy areas |
| Monthly interest paid | About 80 hours | Multiply and convert |
| One-time cost to remove 100 flags | About 100 to 150 hours | Time a few trial removals |
| Payback period | Roughly 1 to 2 months | Divide cost by monthly interest |
These numbers are only an illustration, and your own will differ. The point is the method: make the cost visible, compare it with the cost of the cure, and let the comparison speak.
Tell stories, not only numbers
A single memorable incident is worth a page of statistics. If a confusing flag once delayed a release by a day, or caused a short outage, tell that story plainly and without blame. People remember stories, and stories turn an abstract worry into a concrete reason to act.
Servicing a car feels like a nuisance until you compare its small, regular cost with the price of a broken engine. Nobody argues that servicing is exciting, but nearly everyone agrees it is cheaper than ignoring it. Flag cleanup is the regular service for your codebase.
Ask for something small first
Do not ask for a six-month programme. Ask for one afternoon, one team and one clear measure of success. When that small trial shows fewer flags, simpler code and no incidents, the next request is much easier. Credibility is built one small success at a time.
Connect cleanup to goals people already care about
- Faster delivery. Simpler code means shorter changes and fewer surprises during release.
- Reliability. Fewer unknown switches means fewer unplanned incidents.
- Onboarding. New hires become productive sooner when the codebase tells a clear story.
- Security and compliance. A clean inventory with owners makes audits easier.
- Cost. Less dead code and fewer unused resources reduce effort and spending.
Report cleanup results in the same meetings where feature results are reported. When removal sits beside launches in the update, it is seen as real work.
28Dashboards and Reports for Flag Health
A small, honest dashboard keeps the whole team aware of the state of the drawer.
What a flag health page should show
You do not need a fancy tool. A single page, refreshed weekly by a script, is enough. It should answer five questions at a glance: how many flags exist, how old they are, who owns them, which are past their removal date, and whether the list is growing or shrinking.
Flag count over time
A simple line by month. A rising line is the earliest visual warning that creation is outrunning removal.
Age profile
How many flags fall into each age band, such as under thirty days, up to ninety, up to a year, and older.
Overdue flags by team
A short list grouped by owner, so each team sees only what it must act on.
Ownership coverage
The percentage of flags with an owner tag. The goal is as close to one hundred percent as possible.
Created versus removed
Last month’s balance, with a note on whether the debt is growing, steady or shrinking.
Permanent flags review
Kill switches and entitlements with their last review date, so none is forgotten.
flowchart LR A["Flagsmith REST API"] --> B["Weekly report job"] B --> C["Compute age, owners, sameness, overdue"] C --> D["Store snapshot for trend charts"] D --> E["Publish health page"] C --> F["Post overdue lists to team channels"] E --> G["Monthly review meeting"] F --> H["Owners act on their flags"]
Keep snapshots to see trends
A single report tells you where you are. A series of reports tells you where you are heading. Save a snapshot each week, even if it is just a small file, so you can draw trend lines and show that the work is paying off. Snapshots also help in audits, because they prove what the flag inventory looked like on a given date.
Make the page friendly
A health page nobody reads is wasted. Keep it short, use plain words, show the trend first and the lists second, and link each flag to its place in Flagsmith and its ticket. Avoid blaming individuals. Group by team, and phrase it as an invitation: “These five flags are ready for retirement.”
Beware of vanity numbers
A falling total looks good, but it can be gamed: archive flags instead of cleaning code, and the count drops while the debt remains. Pair the flag count with a measure that reflects real code removal, such as the number of flag checks found by a code search. If the number of checks in the code falls along with the flag count, the improvement is real.
Do not set targets that reward the wrong behaviour. If people are praised for reducing the count at any cost, they may delete flags carelessly. Praise safe, well-tested removals, and celebrate the absence of incidents as much as the drop in numbers.
A small set of questions for the monthly review
- Did we create more flags than we removed? If so, why?
- Which team has the most overdue flags, and what is blocking them?
- Are any permanent flags overdue for review?
- Did any removal cause a surprise, and what did we learn?
- What is the single most valuable flag we could retire next month?
Ten minutes on these questions each month keeps the practice alive. The aim is not perfection. It is steady attention, and steady attention is what stops the drawer from filling with keys again.
Five questions to ask before you create any flag
Prevention is the cheapest cleanup. Before creating a new flag, pause for a minute and answer five short questions. Doing so takes almost no time and prevents most of the debt described in this guide.
Do we really need a flag?
If the change is tiny, safe and easy to reverse by releasing again, a flag may add more complexity than it removes.
What kind of flag is this?
Release, experiment, operational or permission. The answer decides how long it should live and how it will be reviewed.
Who owns it?
Name a team, not only a person, so that responsibility survives holidays and job changes.
When will it be removed?
Write a date or a condition, such as “thirty days after full rollout,” and open the removal task now.
What is the safe default?
Decide what the app does when the flag cannot be read, and make sure that behaviour is the stable, tested one.
These five questions work for a tiny change and for a company-wide programme alike. Teams that make them a habit rarely have dramatic flag problems, because small issues are noticed and fixed while they are still small, long before they can interfere with a launch, an experiment or an incident response.
A culture that tidies as it goes
In the end, flag hygiene is a matter of culture more than tools. In a healthy team, removing a flag is as normal as writing a test. Nobody needs to be asked, because everyone remembers that a feature is not finished until its scaffolding is gone. Leaders set this tone by praising tidy work, by giving time for it, and by never treating cleanup as something done only when there is nothing better to do. Newcomers pick up the habit by watching how the team behaves, which is why the first few weeks of a new engineer are the best moment to show them how flags are created, tracked and retired. A culture like this does not appear overnight, but it grows steadily from small, repeated, visible actions, and it keeps paying back long after the first cleanup day has been forgotten.
Write down what you learn
Every cleanup teaches something. A flag that turned out to guard a rare report, an old app version that still read a switch, a segment that three flags shared: each lesson is worth a sentence. Keep a short shared note of surprises and how they were handled, and link it from your removal runbook. The next person to retire a flag will read it, avoid the same trap and add a lesson of their own. Over a year, that small note becomes the most practical guide your team owns, because it describes your systems, your habits and your history, not someone else’s.
It also helps to say thank you. When a teammate removes a stubborn flag that has haunted a service for years, mention it in the team channel. Recognition is cheap, it is remembered, and it tells everyone that tidy work is valued. People repeat what is noticed and appreciated, and that quiet encouragement does more for flag hygiene than any rulebook or tool ever could.
Finally, keep your expectations realistic and your tone kind. Some flags will turn out to be harder to remove than anyone expected, and some mistakes will happen along the way. Treat each one as information about the system, not as a failure of a person. Blameless reviews, short written notes and a steady rhythm of small improvements will carry a team much further than pressure ever does. The goal is not a perfectly empty flag list. The goal is a list in which every item has a purpose, an owner and a plan, so that nobody ever again has to wonder what a mysterious switch does, or whether it is safe to touch.
If you take only one idea from this guide, let it be that every flag deserves an ending. Decide that ending on the day the flag is born, write it where everyone can see it, and check on it regularly. Everything else in this guide is detail in service of that single, simple promise.
29Frequently Asked Questions
Quick answers to the questions beginners ask most often.
30Summary and Key Takeaways
The whole guide on one page.
Key Takeaways
- Flags are cheap to create and costly to keep. Without a plan, they pile up into flag debt that slows reading, testing and releasing, and raises the risk of nasty surprises.
- Know the four kinds. Release and experiment flags are temporary and must expire. Kill switches and permission flags are long-lived and need owners and reviews.
- Prevent first. Create every flag with a clear name, a description, an owner, a kind and a removal date, and open the removal task on the same day.
- Make debt visible. Combine age, sameness across environments, usage, ownership and code search, and track the monthly balance of flags created versus removed.
- Remove in the right order. Confirm the final value, remove the code, release, wait, archive, wait again, then delete, and review overrides, environments and old app versions along the way.
- Let machines find, let humans decide. Automate reports, tags and reminders with least-privilege keys, and keep deletion decisions with people.
- Make it a habit. A short weekly glance, a monthly review and a quarterly cleanup day keep the list small, trusted and safe.