Slide 1

Slide 1 text

Mastering Feature Flags Best Practices and Implementation with Firebase Remote Config Domen Lanišnik Android Engineer, Lyft

Slide 2

Slide 2 text

Agenda ● Basics ● Benefits and drawbacks ● Best practices ● Advanced uses ● Getting started with Firebase Remote Config ● Summary

Slide 3

Slide 3 text

What is a Feature Flag ● Simple boolean variable ● Control remotely whether a feature is enabled ● No need to rebuild and re-release the app Feature Flag Turned OFF Feature Flag Turned ON

Slide 4

Slide 4 text

What is a Feature Flag if (isFeatureEnabled("shareFeatureEnabled")) { // show Share button } if (isFeatureEnabled("useNewComposeScreen")) { // open new Compose based screen } else { // open old View based screen }

Slide 5

Slide 5 text

Why Use Feature Flags ● Protect against critical bugs or crashes ● Decouple from the release process ● Control which users get the feature ● Avoid long-lived feature branches ● Support one-time features ● Run A/B experiments

Slide 6

Slide 6 text

What to Watch Out For ● Overusing feature flags (complexity) ● Dependant feature flags ● Increased testing difficulty ● Stale feature flags (tech debt)

Slide 7

Slide 7 text

Best Practices ● Put new features under feature flags and ship early ● Have a clear naming convention ● Define ownership ● Perform regular reviews for stale flags ● Avoid dependent flags

Slide 8

Slide 8 text

Different Types of Feature Flags ● Int, String, Double, Lists, Json, … ● Allows for different configurations ● Enables experimenting with different values

Slide 9

Slide 9 text

Kill Switches ● Used for critical paths ● Refreshed often ● Disable an important feature in case of an issue ● Should not be same as the main feature flag

Slide 10

Slide 10 text

A/B Testing ● Divide the user base into two groups ● Gather analytics and metrics ● Decide whether to ship the new feature

Slide 11

Slide 11 text

How to Start Using Feature Flags ● Implement your own feature management service ● Use existing open-source libraries ● Use a third-party feature management service

Slide 12

Slide 12 text

Firebase Remote Config ● Cloud service for changing behavior and appearance of apps ● Third-party feature management service ● Offers everything out-of-the-box ● Update values through console or backend APIs ● Android, iOS, Flutter, Web, and Backend

Slide 13

Slide 13 text

Implementation Steps 1. Set up (new) Firebase Project 2. Integrate Firebase SDKs into your app 3. Configure the Remote Config object 4. Fetch and activate values 5. Read values from Remote Config backend 6. Listen for updates

Slide 14

Slide 14 text

1. Set up a new Firebase Project

Slide 15

Slide 15 text

1. Set up a new Firebase Project

Slide 16

Slide 16 text

1. Set up a new Firebase Project

Slide 17

Slide 17 text

1. Set up a new Firebase Project

Slide 18

Slide 18 text

2. Integrate the SDK

Slide 19

Slide 19 text

2. Integrate the SDK

Slide 20

Slide 20 text

2. Integrate the SDK

Slide 21

Slide 21 text

2. Integrate the SDK

Slide 22

Slide 22 text

2. Integrate SDK dependencies { // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:32.3.1")) // Add the dependencies for the Remote Config and Analytics libraries implementation("com.google.firebase:firebase-config-ktx") implementation("com.google.firebase:firebase-analytics-ktx") }

Slide 23

Slide 23 text

2. Integrate the SDK

Slide 24

Slide 24 text

3. Create a new Feature Flag

Slide 25

Slide 25 text

3. Create a new Feature Flag

Slide 26

Slide 26 text

3. Create a new Feature Flag

Slide 27

Slide 27 text

3. Create a new Feature Flag

Slide 28

Slide 28 text

4. Initialize Remote Config class FeatureChecker { private val remoteConfig = FirebaseRemoteConfig.getInstance() init { val configSettings = remoteConfigSettings { minimumFetchIntervalInSeconds = 3600L } remoteConfig.setConfigSettingsAsync(configSettings) } }

Slide 29

Slide 29 text

5. Set Default Values remoteConfig.setDefaultsAsync( mapOf( "detailsScreenEnabled" to false, "descriptionMaxLineCount" to 2L, "detailsNavigation" to "BOTTOM_SHEET" ) )

Slide 30

Slide 30 text

6. Fetch Remote Values suspend fun fetchFeaturesConfig(): Boolean { return remoteConfig.fetchAndActivate().await() } ● Blocking during app startup (splash screen) ● Async and update immediately ● Async and use new values next time

Slide 31

Slide 31 text

7. Read Values fun isFeatureEnabled(featureFlagName: String): Boolean { return remoteConfig.getBoolean(featureFlagName) } fun getLongValue(key: String): Long { return remoteConfig.getLong(key) }

Slide 32

Slide 32 text

6. Read Values class ViewModel(private val featureChecker: FeatureChecker) : ViewModel() { private val _detailsScreenEnabled: MutableStateFlow = MutableStateFlow(false) val detailsScreenEnabled: StateFlow = _detailsScreenEnabled init { viewModelScope.launch { _detailsScreenEnabled.update { featureChecker.isFeatureEnabled("detailsScreenEnabled") } } } }

Slide 33

Slide 33 text

6. Using it in Compose with a ViewModel val detailScreenEnabled = viewModel.detailsScreenEnabled .collectAsState() .value if (detailsButtonEnabled) { IconButton( onClick = {}, ) { Icon( Icons.Default.ArrowForward, contentDescription = "Open details" ) } }

Slide 34

Slide 34 text

8. Observe Updates in Real-Time ● Receive new values as soon as published ● Opens HTTP connection to Remote Config backend Source: https://firebase.google.com/docs/remote-config/real-time?platform=android

Slide 35

Slide 35 text

8. Observe Updates in Real-Time suspend fun observeFeatureConfigChanges() = callbackFlow { firebaseRemoteConfig.addOnConfigUpdateListener(object : ConfigUpdateListener { override fun onUpdate(configUpdate: ConfigUpdate) { firebaseRemoteConfig.activate().addOnCompleteListener { trySend(configUpdate.updatedKeys) } } override fun onError(error: FirebaseRemoteConfigException) { close(error.cause) } }) awaitClose { } }

Slide 36

Slide 36 text

8. Observe Updates in Real-Time featureChecker.observeFeatureConfigChanges() .filter { it.contains("detailsScreenEnabled") } .map { featureChecker.isFeatureEnabled("detailsScreenEnabled") } .collectLatest { featureEnabled -> _detailsScreenEnabled.update { featureEnabled } }

Slide 37

Slide 37 text

7. Observe Updates in Real-Time

Slide 38

Slide 38 text

Conditions

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

Additional Capabilities ● A/B experiments ○ Used with Google Analytics ● Personalization ○ Uses ML to deliver custom experience to each user ○ Automatically achieve maximum conversion ○ Can be useful for showing ads, adjusting difficulty level in a game, …

Slide 43

Slide 43 text

Setting up an A/B Experiment ● how to set up ● how to target specific users ● code examples

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

Firebase Remote Config Limitations ● Free to use for unlimited daily active users ● Maximum 2000 parameters ● Parameter keys can be up to 256 characters long ● Maximum 500 conditions ● Throttling (default is 12 hours) ● Up to 300 total A/B experiments (max 24 running)

Slide 48

Slide 48 text

Summary ● Feature flags are a powerful tool ● Make building and releasing mobile apps both safer and faster ● Benefits outweigh the drawbacks ● Stick to the best practices ● Easy to get started with Firebase Remote Config

Slide 49

Slide 49 text

Thank you! domenlanisnik @DomenLanisnik @domen.lanisnik