Skip to content

Setting Up Feature Flags

What you'll learn

  • Generating the Feature Flag SDK with provider implementations
  • Choosing between Firebase Remote Config and Flagr backends
  • Using feature flags to gate functionality at runtime
  • Setting up A/B testing and gradual rollouts

Prerequisites

  • An existing Archipelago monorepo (see Monorepo Scaffolding)
  • Firebase configured (if using Remote Config provider)

Step 1: Generate the Feature Flag SDK

bash
archipelago generate feature_flag_sdk

You will be prompted for:

  • appNameMyApp (must match your monorepo app name)
  • isForMonorepotrue
  • includeRemoteConfigtrue (Firebase Remote Config provider)
  • includeFlagrfalse (Flagr provider, optional)

Or use a config file:

json
{
  "appName": "MyApp",
  "isForMonorepo": true,
  "includeRemoteConfig": true,
  "includeFlagr": false
}
bash
archipelago generate feature_flag_sdk --config flags_config.json

Step 2: Understand the Generated Structure

The Feature Flag SDK uses the API/Impl split for vendor-agnostic flag evaluation:

infrastructure/
├── feature_flag_sdk_api/
│   └── lib/src/
│       ├── feature_flag_client.dart        # Abstract flag contract
│       ├── flag_value.dart                 # Typed flag value wrapper
│       └── flag_key.dart                   # Flag key definitions
└── feature_flag_sdk_impl/
    └── lib/src/
        ├── remote_config_client.dart       # Firebase Remote Config impl
        ├── flagr_client.dart               # Flagr impl (if enabled)
        ├── local_flag_client.dart           # Local overrides for dev
        └── di/
            └── feature_flag_module.dart    # DI registration

Step 3: Define Flag Keys

Register your feature flags in the flag key definitions:

dart
// feature_flag_sdk_api/lib/src/flag_key.dart
abstract class FlagKey {
  static const newCheckout = 'new_checkout_flow';
  static const darkMode = 'dark_mode_enabled';
  static const maxRetries = 'max_retry_count';
}

Step 4: Evaluate Flags in Features

Features depend on feature_flag_sdk_api and query flags through the abstraction:

dart
final flags = getIt<FeatureFlagClient>();

// Boolean flags
if (await flags.getBool(FlagKey.newCheckout)) {
  // Show new checkout flow
} else {
  // Show legacy checkout
}

// Typed values
final maxRetries = await flags.getInt(FlagKey.maxRetries, defaultValue: 3);

// Listen to flag changes
flags.onValueChanged(FlagKey.darkMode).listen((enabled) {
  themeController.setDarkMode(enabled);
});

Step 5: Local Overrides for Development

Use the local flag client to override values during development without touching the remote backend:

dart
// In debug bootstrap
final localFlags = LocalFlagClient(overrides: {
  FlagKey.newCheckout: true,
  FlagKey.maxRetries: 5,
});
getIt.registerSingleton<FeatureFlagClient>(localFlags);

Key Customization Points

CustomizationWhere to Change
Add new flag providerCreate new FeatureFlagClient impl
Set default flag valuesremote_config_client.dart — defaults map
Fetch intervalremote_config_client.dart — cache expiration
Add user targetingExtend FeatureFlagClient with user context

Next Steps

Built by Banua Coder