Feature Flags
Decouple deployment from release - toggles, targeting, gradual rollouts, experiments, and the platforms that run them
Feature Flags
A feature flag is a conditional in your code whose value is controlled at runtime by configuration, not by the build. Deploy code with a new feature off; flip it on for one user, then 5%, then everyone — without touching the artifact.
Why Use Them
| Without flags | With flags |
|---|---|
| Deploy = release | Deploy is invisible; release is a config flip |
| Rollback = redeploy old version | Rollback = flip the flag off |
| Risk concentrated at deploy time | Risk distributed: incremental exposure |
| QA blocks the entire branch | Hide unfinished work behind a flag, ship to main |
| Trunk-based development is hard | It's the easy path |
| A/B test = separate deploy paths | Built-in experiment framework |
Four Kinds of Flags
| Type | Lifespan | Purpose | Example |
|---|---|---|---|
| Release | Days to weeks | Hide unfinished work; gradual rollout | enable_new_checkout |
| Experiment | Weeks to months | A/B test variants and measure | pricing_v2_experiment |
| Permission / Entitlement | Long-lived | Per-customer / plan capabilities | customer_has_sso |
| Ops / Kill Switch | Long-lived | Disable a feature in an incident | disable_recommendation_engine |
The four have different lifecycles. Treat them differently — release flags should die; ops flags live forever.
The Players
| Platform | Notes |
|---|---|
| LaunchDarkly | SaaS leader; rich targeting; experimentation suite |
| Unleash | Open-source (self-host or cloud); Apache-2 licensed |
| Flagsmith | Open-source SaaS + self-host; per-environment |
| PostHog | Product analytics + feature flags + session replay; open-source |
| Split | Strong on experimentation + metrics |
| ConfigCat | Simple, dev-friendly, cheaper than LaunchDarkly |
| OpenFeature | Vendor-neutral SDK spec; switch providers without rewriting |
| Statsig | Free tier + strong experimentation; popular in startups |
| AWS AppConfig / Cloud-managed | Tightly integrated with cloud workloads |
OpenFeature is the spec to know. It standardises the SDK API so your app code doesn't depend on a specific vendor.
Learning Path
1. Getting Started
Self-host Unleash with Docker Compose, integrate from a Node app, evaluate a flag
2. Patterns
Targeting rules, gradual rollout, kill switches, A/B testing, dependent flags
3. Best Practices
Flag lifecycle, debt management, evaluation latency, fail-safe defaults, server-side vs client-side
A Flag in Code Looks Like
// Without flags
if (user.country === 'US') {
return renderNewCheckout();
}
return renderOldCheckout();
// With flags
if (await flags.isEnabled('new_checkout', { userId: user.id, country: user.country })) {
return renderNewCheckout();
}
return renderOldCheckout();The condition moved from code to configuration. The new checkout can roll out to US users on a percentage, the experiment can compare conversion rates, and one ops command can disable it during an incident — without changing or redeploying the application.
Feature flags create technical debt. Every flag is a branch in your code that someone has to remember to delete. A six-month-old release flag is a smell. Track them, set expiry dates, and clean up — see Best Practices.
When Flags Aren't the Answer
- Major architectural changes — a flag can't bridge incompatible data models.
- Schema migrations — flags toggle behavior, not database structure.
- One-time setup (initial onboarding, account creation) — use a different mechanism.
- Anything where both branches incur full cost — code complexity, latency, memory.
Flags are about behavior under conditions. If both branches always run, you've just added overhead.