Infrastructure SDKs
How to add feature flags to a Flutter app
Free Reference for feature_flag_sdk: every variable, option and package it generates. Command: archipelago generate feature_flag_sdk
Generate the Feature Flag SDK, pick Firebase Remote Config or Flagr, evaluate flags with FeatureFlagManager, and learn the cache and aggregation strategies.
What you'll learn
- Generating the Feature Flag SDK with a vendor package
- Choosing between Firebase Remote Config and Flagr
- Evaluating flags with
FeatureFlagManager - Understanding the cache and aggregation strategies
- Adding your own provider
Prerequisites
- An existing Archipelago monorepo (see Monorepo Scaffolding)
- For Remote Config, a Firebase project configured with
flutterfire configure - For Flagr,
network_sdkinstalled first (see Network SDK Setup)
Step 1: Generate the Feature Flag SDK
Pick a vendor at project creation with featureFlagVendor, and the generator does this for you. To add it later, run:
archipelago generate feature_flag_sdkThe prompts are:
- appName: your app name, for example
MyApp - isForMonorepo: leave this as
true - featureFlagVendor:
remote_config(default),flagr,customornone
Or use a config file:
{
"appName": "MyApp",
"isForMonorepo": true,
"featureFlagVendor": "remote_config"
}archipelago generate feature_flag_sdk --config flags_config.jsonflagr needs network_sdk first. The brick does not generate it or warn when it is missing. The workspace fails to compile without it.
With custom or none, only the core packages are generated. You write a FeatureFlagProvider yourself and register it.
Step 2: Understand the Generated Structure
The core packages are always generated. Only one vendor package is kept.
infrastructure/
├── feature_flag_api/ # FeatureFlagProvider, results, delegates
├── feature_flag_impl/ # Manager, cache, aggregator, initializer
├── remote_config_feature_flag_impl/ # If remote_config
└── flagr_feature_flag_impl/ # If flagrfeature_flag_impl depends on feature_flag_api only. The post-generation hook registers FeatureFlagImplPackageModule in the app injector.
Step 3: Evaluate Flags
Flag keys are plain strings you define in your own code. Features take FeatureFlagManager by constructor:
final enabled = await _flags.isEnabled(flagKey: 'new_checkout');
final result = await _flags.evaluate(
flagKey: 'new_checkout',
defaultValue: false,
);FeatureFlagResult has enabled, an optional variantKey and variantValue for A/B tests, providerId, evaluatedAt and metadata.
The manager checks an in-memory cache first. The default is 5 minutes and 100 entries. Call invalidateCache('new_checkout') to force a fresh read.
Step 4: Start the Providers After Launch
FeatureFlagInitializer.register(getIt) runs during pre-launch. It registers the cache and the manager as lazy singletons. FeatureFlagInitializer.initialize(getIt) runs in the post-launch phase and starts the providers.
The generated post_launch_initializer.dart already wraps this call. You add nothing.
Step 5: Know the Aggregation Strategy
With more than one provider, the manager combines results by AggregationStrategy:
firstMatchpriorityWithFallback(default)unanimousanyEnabled
Step 6: Configure the Vendor
Remote Config
initialize() fetches and activates values. The minimum fetch interval is 12 hours in release builds and 1 minute in debug builds. Firebase bills fetches above 100,000 a day per project, so keep the release interval long.
- Call
forceRefresh()to test a release build against fresh values. - Use Realtime Remote Config for kill switches. The provider's
onFlagChanged()listens toonConfigUpdated.
Flagr
The provider calls POST {baseUrl}/api/v1/evaluation through the HttpClient from network_sdk_api. Set FLAGR_BASE_URL in .env.<flavor> in shared/app_config. Flagr has no bulk or push API. evaluateAll() returns an empty map and onFlagChanged() returns null.
Step 7: Add Your Own Provider
Implement FeatureFlagProvider and register it. A vendor module registers its key with FeatureFlagProviderRegistry.instance.register(<key>) in its constructor. The reserved keys in FeatureFlagInjectorKey include launchDarkly, unleash, split, optimizely and customBackend.
Step 8: Override Flags While Developing
Generate app_debugger_feature_flag. It adds a FeatureFlagDelegate that runs before the real providers. You change values from the debug panel with no backend change. Register your own delegate with FeatureFlagDelegateRegistry.instance.register(...).
Consent
EvaluationContext.toMap() includes email only when ConsentPurpose.targeting is granted.
Key Customization Points
| Customization | Where to Change |
|---|---|
| Add a flag provider | A new FeatureFlagProvider and its registry key |
| Cache time and size | FeatureFlagCache in feature_flag_impl |
| Remote Config fetch interval | The provider constructor in register_module.dart |
| Aggregation strategy | The FeatureFlagAggregator setup |
Next Steps
- Set up analytics to track flag-driven experiments
- Configure monitoring to alert on flag evaluation errors