Feature Flags
Roll out features gradually without deploying new code. Feature flags let you control what users see from the CADENCE dashboard.
Feature flags vs. experiments
Both control what users see, but they serve different purposes:
| | Feature Flags | Experiments | |---|---|---| | Purpose | Ship safely | Measure impact | | Output | Boolean (on/off) | Variant name (string) | | Tracking | No automatic tracking | Auto exposure tracking | | Rollout | Percentage-based (0–100%) | Traffic allocation + variant weights | | Dashboard | Enable/disable toggle | Full results with statistics |
Use feature flags when you want to gradually enable a feature. Use experiments when you want to measure whether a change improves a metric.
Creating a feature flag
- Navigate to your project in the dashboard
- Create a new feature flag
- Set a key (kebab-case, e.g.,
new-checkout-flow) - Set enabled status and rollout percentage
The rollout percentage controls what fraction of users see the feature. Set it to 5% to test with a small group, then increase to 25%, 50%, and eventually 100%.
Using isFeatureEnabled()
The simplest way to check a flag. Returns true or false:
await cadence.ready()
if (cadence.isFeatureEnabled('new-checkout-flow')) {
return <NewCheckout />
} else {
return <LegacyCheckout />
}
The check is deterministic: the same user always gets the same result for the same flag, based on a hash of their user ID and the feature key.
Using getFeatureValue()
For feature values beyond simple booleans, use getFeatureValue():
const price = cadence.getFeatureValue('hero-price', 9.99)
const limit = cadence.getFeatureValue('upload-limit-mb', 10)
const theme = cadence.getFeatureValue('color-theme', 'light')
getFeatureValue() has a two-step resolution:
- Checks experiment overrides first. If an active experiment variant has a matching
feature_overrideskey, that value is returned. - Falls back to the feature flag. If the flag is enabled for this user, returns
true. Otherwise returns yourdefaultValue.
This means experiments can override feature values dynamically, which is useful for testing different configurations.
Common patterns
Dark launches
Deploy a feature behind a flag, then enable it gradually:
// Day 1: deployed but off (0% rollout)
// Day 2: enable for 5% of users
// Day 5: increase to 25%
// Day 10: increase to 100%
if (cadence.isFeatureEnabled('redesigned-dashboard')) {
return <NewDashboard />
}
return <CurrentDashboard />
Kill switches
Wrap risky features in a flag so you can disable them instantly from the dashboard:
if (cadence.isFeatureEnabled('ai-recommendations')) {
return <AIRecommendations />
}
return <ManualRecommendations />
If the AI service goes down, disable the flag from the dashboard. No deploy needed.
Experiment-driven overrides
Combine experiments with feature values. Create an experiment where each variant sets different feature override values:
// The experiment assigns a variant, and the variant's feature_overrides
// set the price value. getFeatureValue() picks it up automatically.
cadence.getVariant('pricing-experiment')
const price = cadence.getFeatureValue('monthly-price', 29)
Best practices
Name flags descriptively. new-checkout-flow is better than flag-1 or test. Your future self will thank you.
Clean up after full rollout. Once a feature is at 100% and stable, remove the flag from your code. Flag debt is tech debt.
Don't nest flags. Avoid checking one flag inside another. It makes behavior hard to predict and debug.
Use experiments for measurement. If you want to know whether a feature improves a metric, use an experiment with getVariant() instead of a flag. Experiments track exposures automatically and provide statistical analysis.
Next steps
- API Reference — Full method signatures for
isFeatureEnabled()andgetFeatureValue() - Creating Tests — When you need measurement, not just rollout