Skip to content
Back to archipelago.banuacoder.com

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_sdk installed 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:

bash
archipelago generate feature_flag_sdk

The prompts are:

  • appName: your app name, for example MyApp
  • isForMonorepo: leave this as true
  • featureFlagVendor: remote_config (default), flagr, custom or none

Or use a config file:

json
{
  "appName": "MyApp",
  "isForMonorepo": true,
  "featureFlagVendor": "remote_config"
}
bash
archipelago generate feature_flag_sdk --config flags_config.json

flagr 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.

text
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 flagr

feature_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:

dart
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:

  • firstMatch
  • priorityWithFallback (default)
  • unanimous
  • anyEnabled

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 to onConfigUpdated.

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(...).

EvaluationContext.toMap() includes email only when ConsentPurpose.targeting is granted.

Key Customization Points ​

CustomizationWhere to Change
Add a flag providerA new FeatureFlagProvider and its registry key
Cache time and sizeFeatureFlagCache in feature_flag_impl
Remote Config fetch intervalThe provider constructor in register_module.dart
Aggregation strategyThe FeatureFlagAggregator setup

Next Steps ​