What are feature flags?
A plain-English explanation of feature flags: what they are, how they differ from feature toggles, the four ways teams use them, and how they enable continuous delivery.
A feature flag is a switch in your code that decides whether a piece of functionality runs, evaluated at runtime instead of being fixed at deploy time. In its simplest form it’s a conditional: if (flagEnabled) { newThing() } else { oldThing() }. The power isn’t in the if — it’s in moving control of that condition out of the codebase and into a dashboard, so you can change behavior in production without shipping new code.
This is the foundational concept. Once you have it, two follow-on questions usually come next — how do I implement this in my framework, and how do I keep flags from piling up? Both have their own dedicated guides (using feature flags in Angular and feature flag management); this article covers the fundamentals they build on.
What are feature flags, exactly?
A feature flag (also called a feature toggle) is a named condition whose value is controlled outside your deployment pipeline. Instead of “this code is live because we deployed it,” the model becomes “this code is deployed, and it’s live because the flag is on.”
That decoupling of deploy from release is the entire point. You can:
- Merge unfinished work to your main branch behind an off flag, and keep deploying continuously.
- Turn a feature on for 5% of users, watch your error rate, then expand.
- Ship a feature to internal staff or one customer before everyone else.
- Disable a misbehaving feature from the dashboard, without a rollback deploy.
Each flag has a key (like release-new-checkout), a value (on or off), and optionally a set of targeting rules that decide who sees what. Your code asks the flag whether it’s enabled; the dashboard decides the answer.
Feature toggle vs feature flag: is there a difference?
Short answer: no. “Feature toggle” and “feature flag” are the same concept under two names. Martin Fowler’s influential write-up used “feature toggle,” while most commercial tooling settled on “feature flag.” You’ll see both, sometimes in the same sentence.
If you want to be precise, people occasionally use the words to emphasize different lifespans — a “toggle” sounds like a long-lived operational switch, a “flag” sounds like a temporary marker on a release. But this distinction isn’t standardized and no tool enforces it. Treat the terms as interchangeable. What actually matters is the flag’s intent and lifespan, which you encode in its name rather than in which word you use.
The four things feature flags are used for
Most flags fall into one of four categories, and knowing which one you’re creating tells you how long it should live.
Release flags gate a new feature during a gradual rollout. You merge to main behind an off flag, deploy, then enable it — for internal users first, then a percentage, then everyone. These are temporary; remove them once the feature is fully shipped.
Experiment flags run A/B tests. You enable a feature for half your users with a percentage rollout and compare a metric against the half who don’t have it. These have a defined end date — the experiment concludes and the winner ships.
Kill switches are permanent circuit breakers. A flag wrapping a third-party payment integration lets you disable it from the dashboard if the provider goes down — no deploy, and clients pick up the change within about a minute on their next refresh. You never intend to remove these.
Ops flags tune operational behavior — a cache TTL, a rate limit, a batch size. Often permanent, changed occasionally by the people who run the system.
The first two are temporary and should be cleaned up. The last two are load-bearing and stay. Confusing the categories is how codebases end up with hundreds of flags nobody can reason about — which is the core problem feature flag management exists to solve.
How feature flags work under the hood
At the code level, a feature flag SDK gives you a function that takes a flag key and an optional user context and returns a boolean.
import { flaggy } from '@flaggy.io/sdk-js';
const client = flaggy({ apiKey: process.env.FLAGGY_API_KEY });
await client.initialize();
if (client.isEnabled('release-new-checkout', { key: user.id })) {
return renderNewCheckout();
}
return renderLegacyCheckout();
The SDK downloads your ruleset when it initializes and evaluates flags locally — the check is an in-memory lookup, not a network round trip. This matters for two reasons: evaluation adds no latency, and the vendor’s servers aren’t involved every time a flag is read. (It’s also why per-monthly-active-user pricing makes little technical sense — see our breakdown of LaunchDarkly’s pricing.)
The pattern is the same in every language: initialize the client once at startup, share it, and pass a context object so the dashboard can target rules against user attributes. For framework-specific walkthroughs, see our guides on feature flags in JavaScript, using feature flags in React, and using feature flags in Angular.
Feature flags in DevOps and continuous delivery
Feature flags are a core enabler of continuous delivery. They’re what let you practice trunk-based development — everyone commits to main, often, behind flags — without shipping half-finished features to users. The deploy pipeline runs constantly; the flag decides when work becomes visible.
This unlocks a few patterns:
- Continuous deployment without continuous release. Deploy every merge to production; release features on your own schedule by flipping flags.
- Canary releases without traffic routing. A percentage rollout flag gives you canary-style gradual exposure without load balancer surgery. See feature flags as a canary alternative.
- Fast rollback. A failed release is a flag flip away from being off — clients pick up the change on their next background refresh (about a minute), faster and safer than redeploying the previous build.
Choosing a feature flag tool
You can build a basic flag system with a config file and a boolean, and for a handful of flags that’s fine. The moment you want targeting rules, percentage rollouts, an audit trail, and non-engineers flipping flags safely, a dedicated feature flag tool (or feature-flag-as-a-service) earns its place.
Look for:
- A dashboard to manage flags with no code change
- Targeting and segmentation by user attributes
- Percentage rollouts and segment targeting
- A full audit log of every change
- An SDK that evaluates locally, so flags add no latency
- Pricing that doesn’t meter you per active user — since evaluations happen client-side, MAU metering charges you for a metric that doesn’t reflect the vendor’s cost
Flaggy covers all of these on a flat $99/month Team plan — unlimited seats, no MAU fees, with flag management, analytics, and audit log included.
Feature flags FAQ
Are feature flags and feature toggles the same thing? Yes. The terms are interchangeable; “toggle” comes from Martin Fowler’s terminology and “flag” from most commercial tooling.
Do feature flags slow down my app? No, if the SDK evaluates locally. Evaluation is an in-memory lookup against rules downloaded at startup, not a network call per check.
How many feature flags is too many? There’s no hard limit, but every temporary flag you don’t remove is debt. The problem is rarely the count — it’s untracked flags with no owner or removal plan. See feature flag management.
Can non-developers use feature flags? Yes — that’s much of the point. A dashboard lets product managers and support staff flip flags and adjust targeting without a deploy, within the access controls you set.