The nerve-wracking thing about shipping is that the moment your code goes live is the moment users hit the new feature, and if it is broken, it is broken for everyone at once. A feature flag takes that single terrifying moment and splits it into two calm ones: you deploy the code with the feature switched off, and then, separately and whenever you like, you switch it on. If it misbehaves, you switch it back off in a second. It is a small idea that changes how it feels to ship.
Ship the code dark, reveal it later
A feature flag is just a conditional that gates a piece of code at runtime, checked against a setting you control from outside the code:
if (flags.isEnabled("new-checkout", user)) {
return newCheckout() // the new path, only if the flag is on
}
return oldCheckout() // otherwise, the old, known-good path
Think of it as wiring a light into the wall and leaving the switch off. The wiring, the risky, fiddly part, is done during calm working hours. The code is sitting in production, tested, but inert. Flipping the switch is a separate act you do when you are ready, and it is instant and reversible. You are never rewiring the wall in front of a live audience.
Deploy and release stop being the same moment
This is the sentence that makes it click: a deploy moves code to production, a release exposes a behavior to users, and a flag lets those be two different events. Without flags they are welded together, and every deploy is a launch. With flags, you deploy all week, quietly, and choose the launch moment on its own.
flowchart LR W[Write the feature] --> D[Deploy to production, flag OFF] D --> L[Code is live but invisible to users] L --> R[Flip the flag ON when ready] R --> U[Users see the feature] R -.something wrong.-> D2[Flip OFF instantly, no redeploy]
This also unlocks a calmer way to work. Big features can be merged in small pieces behind an off flag, so the code lands bit by bit instead of in one giant risky drop, and nobody sees it until it is whole.
The off switch that means go back to what worked
The single most valuable use is the kill switch. A feature goes live, something breaks, latency spikes or errors climb, and instead of scrambling to roll back a deployment, you flip one switch and the app returns to its old behavior instantly. No redeploy, no waiting for a build, no 2am panic.
IMPORTANT
Keep the convention that off always means the old, safe behavior. When it is 2am and something is on fire, the on-call person should be able to reason “turn it off, go back to what worked” without thinking. A flag whose off state does something surprising is worse than no flag.
Turn it on for one percent first
Because the flag decides per request, you do not have to turn a feature on for everyone at once. You can release it progressively: switch it on for your own team first, then 1% of users, then 5%, then 25%, watching your error rates and metrics at each step and only widening if things stay healthy. This is a canary release at the feature level, and it means a bad feature hurts 1% of people for five minutes instead of everyone for an hour.
flowchart LR T[Internal team] --> P1[1% of users] --> P5[5%] --> P25[25%] --> All[100%] P5 -.metrics bad.-> Off[Flip off, investigate]
The same targeting powers other things: show a feature only to beta users, only to one country, or only to accounts on a certain plan. The flag is a runtime decision, so it can depend on who is asking.
The four jobs a flag does
Not all flags are the same, and knowing which kind you are making tells you how long it should live.
| Type | What it is for | Lifespan |
|---|---|---|
| Release | Hide an unfinished feature until it is ready | Temporary; delete after launch |
| Experiment | Show variant A or B to measure which is better (A/B test) | Temporary; delete after the test |
| Ops / kill switch | Turn a risky or expensive subsystem off fast | Long-lived on purpose |
| Permission | Gate a feature to certain plans or users (entitlement) | Long-lived, part of the product |
The catch: every flag is a small debt
Here is the part the tutorials skip, and it is the maintenance lesson this blog keeps returning to.
Every if (flag) is a fork in your code, and a temporary flag that never gets removed is dead weight
forever: two code paths to reason about, one of which no longer matters. Let enough of them pile up
and you get a codebase nobody can read, plus real engineering time spent just tracing what is still
live.
WARNING
A release or experiment flag is supposed to die once its feature has fully shipped. Treat removing it as part of finishing the feature, not an optional cleanup for later, because “later” never comes. Give temporary flags an expiry from the day you create them, and schedule the cleanup. This is the same discipline as the rest of keeping an app alive: the tool that saves you today becomes the mess that slows you down if you never tidy it.
The tools you actually reach for
You can start with nothing more than a config value your app reads. Dedicated platforms add targeting, gradual rollout, audit logs, and automatic stale-flag cleanup.
| Job | Popular tools | Note |
|---|---|---|
| Just start | A config file or an environment variable | Free; enough for a single on/off |
| Open-source platform | Flagsmith, Unleash, GrowthBook | Free to self-host; GrowthBook also does A/B tests |
| Hosted platform | LaunchDarkly | Paid; targeting, rollouts, stale-flag tracking, RBAC |
A launch becomes a dial, not a leap
The lesson is that feature flags turn shipping from a single leap into a dial you control. Deploy becomes routine and boring, release becomes a deliberate choice you can make gradually and undo instantly, and a broken feature becomes a switch you flip rather than a fire you fight. The price is discipline: each flag is a small debt, and the teams that win are the ones who delete them on time. Add that habit, and you get to ship with far less fear.
Separate the deploy from the reveal, and keep the dial clean.
Sources
- LaunchDarkly: feature flags 101, use cases, benefits, and best practices for decoupling deploy from release and the kill switch
- Harness: canary releases and feature flags explained for progressive rollout at the feature level
- Flagsmith: deployment strategies and how feature flags help for targeting and the flag types
- ABTesting: feature flag technical debt, why it accumulates and how to pay it down (2026) for temporary flags as debt and scheduled cleanup