Feature flag
A runtime switch that turns code paths, models or prompts on or off per user, tenant or percentage without a redeploy.
A feature flag is an if-statement whose condition lives outside the code, in a flag service you can change while the app is running. You can turn a new model on for 5% of users, for one customer, or only for staff, and turn it off in seconds if it misbehaves. Flags are how Canary & ramped rollout releases and kill switches work, and they let teams merge unfinished work without exposing it.
The light switches in a building: the wiring (code) is installed once, and someone at the panel decides which rooms are lit tonight without calling an electrician.
Never deleting release flags. They accumulate into untested combinations, and someone eventually reuses an old flag name for new behaviour, reactivating code paths nobody remembers.
Flags come in kinds with different lifetimes (Hodgson's taxonomy): release flags (days to weeks, then delete), experiment flags (an A/B test's duration), ops/kill switches (permanent, e.g. 'disable tool calling'), and permission flags (entitlements, long-lived). For LLM systems, flag the model id, prompt version, retrieval config and tool availability separately so you can roll back one without the others. Evaluate flags locally from a streamed ruleset (LaunchDarkly, Unleash, Flagsmith, Statsig SDKs all do this) so a flag check is microseconds and survives the flag service being down; define a safe default for every flag in code. Use stable bucketing (hash of user or tenant id) so a user sees one variant per session. OpenFeature provides a vendor-neutral SDK API. Flag debt is real: stale flags multiply code paths (n boolean flags = 2^n combinations) and old flags get repurposed, which is how Knight Capital lost about $440M in 45 minutes in 2012 when a reused flag reactivated dead trading code on one server.
LaunchDarkly, Unleash, Flagsmith or Statsig behind the OpenFeature SDK; local evaluation with streamed rules; safe default coded for every flag; separate flags for model id, prompt version and tool enablement; bucketing by tenant id for B2B; 90-day expiry lint on release flags; flag changes logged to the audit trail.
A legal-contracts review tool adds a clause-extraction agent. Flags: clause_agent.enabled (release, default off), clause_agent.model (string: mid-tier-2026-08 / large-2026-09), tools.web_fetch (kill switch, default off). Rollout: staff → 2 design-partner tenants → 10% → 100% over three weeks. When a provider incident hits, on-call flips clause_agent.model to the fallback in 20 seconds across all pods. Six weeks later the release flag is removed in a cleanup PR with a lint rule that fails builds on flags older than 90 days.
I'd put every model, prompt and tool change behind a flag with a coded safe default, evaluate locally from a streamed ruleset, and give release flags an expiry date enforced in CI. The follow-up: 'what happens if the flag service is down?' The SDK keeps the last ruleset; if it never loaded, the coded default applies, so defaults must be the safe path.
| Kind | Lifetime | LLM example |
|---|---|---|
| Release | days–weeks | new agent behind rollout |
| Experiment | test duration | prompt v7 vs v8 |
| Ops / kill switch | permanent | disable web_fetch tool |
| Permission | long-lived | premium model for plan X |
Numbers worth knowing
- Flag evaluation latency
- <1 ms (local)SDK evaluates cached rules in-process; remote evaluation adds a network hop
- Propagation of a flag change
- ~1–10 sstreaming SDKs; polling SDKs lag by the poll interval
- Combinations from n boolean flags
- 2^n10 live flags = 1,024 paths, most untested
How to decide
| When | Do this |
|---|---|
| Shipping a new model, prompt or tool | Release flag with percentage rollout; delete after 100%. |
| Dependency can fail badly (provider, web tool) | Permanent kill switch with a documented runbook. |
| Entitlement by plan or tenant | Permission flag or the entitlement system, not a release flag. |
| Flag older than 90 days and at 100% | Remove the flag and the dead branch. |
Cost maths
Hosted flag platforms price by seats and monthly active contexts; open-source Unleash or Flagsmith self-hosted costs a small container plus Postgres (~$50–150/month). The cost of not having a kill switch: a 45-minute provider incident at 20k requests/hour with no fallback is ~15k failed requests; with a flag flip to a fallback model it is ~20 seconds of failures.
Operating it
- >50 live flags or flags without owners: add ownership metadata and expiry enforcement
- Experiments interfering with each other: mutual-exclusion layers in the flag platform
- Regulated customers need change history: audit-logged flag changes with approvals
- Flags past expiry date: alert weekly to owning team if >0
- Flag change events: audit log + chat notification for production environments
- Error rate / quality metric split by flag variant: alert if any variant degrades >2× baseline
When it goes wrong
On 1 August 2012 Knight Capital's trading system sent millions of erroneous orders, losing about $440M in roughly 45 minutes.
Market anomalies and internal alerts that were not acted on in time.
Per the SEC's 2013 order, a deployment missed one of eight servers, and a repurposed flag activated long-dead 'Power Peg' code on that server.
The industry lesson: never reuse flag names, delete dead code with its flag, verify deployment completeness, and have a tested kill switch.
Related terms
Where it shows up
Sources
- Feature Toggles (aka Feature Flags) — Pete Hodgson, martinfowler.com, 2017blog
- OpenFeature specification — OpenFeature (CNCF), 2025spec
Check yourself
Three questions. Every option is explained once you answer.