Feature Flags & Experimentation
Use feature flags for safe deploys, gradual rollouts, A/B tests, and kill switches using OpenFeature, LaunchDarkly, or self-hosted Unleash.
Feature flags decouple code deployment from feature release. They enable gradual rollouts (release to 5% of users before 100%), A/B tests, kill switches for instant disable, and per-user or per-tenant feature targeting-all without code changes.
Use the OpenFeature standard for vendor independence. Ship flags with every new feature. Evaluate flags server-side for consistent bucketing. Clean up flags after full rollout - stale flags become technical debt.
Workflow
- Set up OpenFeature with a providerOpenFeature is the CNCF standard - switching providers (LaunchDarkly, Unleash, Flagsmith) requires only changing the provider, not your code.
- Implement gradual rolloutReleasing to 100% immediately risks a bad experience for all users; gradual rollout limits blast radius.
- Run A/B tests with flag variantsA/B tests determine which variation of a feature performs better before fully committing.
- Implement kill switchesWhen a feature causes issues in production, instant disable without a deployment can prevent extended outages.
- Clean up stale flagsFlags accumulate and become hard-coded assumptions - stale flags are a maintenance burden and source of confusion.
Output Format
OpenFeature client integrated, flags wrapped around all new features, gradual rollout configured, A/B test logging, kill switch tested, cleanup schedule tracked.
Examples
Flag evaluation: `const variant = await client.getStringValue("checkout-experiment", "control", { targetingKey: req.user.id, attributes: { plan: req.user.plan, country: req.user.country } })`Gradual rollout rule: `{ "targetingRules": [{ "query": "user.id % 100 < 20", "variant": "treatment" }] }` - 20% of users see treatmentKill switch: `const useNewSearch = await flags.getBooleanValue("search-v2", true); const results = useNewSearch ? await newSearch(q) : await legacySearch(q)`Edge Cases & Gotchas
- Flag evaluation in SSR: evaluate server-side for consistent experiences; avoid client-side evaluation for critical UI paths to prevent flash of different content
- Bootstrap consistency: pass evaluated flags to the client from SSR to prevent the client re-evaluating (and potentially getting a different value) on hydration
- Flag dependencies: avoid flags that depend on other flags - creates evaluation order complexity and makes rollbacks complicated
When to Break These Rules
- For simple boolean configuration that never changes after deploy (feature permanently enabled), environment variables are simpler than a flag service.
Reference Files
OpenFeature spec: https://openfeature.dev/LaunchDarkly: https://launchdarkly.com/docs/Unleash (self-hosted): https://docs.getunleash.io/Flagsmith: https://docs.flagsmith.com/