[MUSIC PLAYING]
DANA SILVER: Hi.
I'm Dana Silver, a software engineer on the Firebase team.
As a developer, you probably know how exciting
it is to launch new features and, at the same time, how
intimidating it can be to ship code to your production apps.
You're likely thinking about when and how
to release the code, how to gather feedback from users,
and what to do if there are bugs.
You can implement feature flagging with Firebase Remote
Config to help reduce production risk and gain
control of your launches, enabling you to ship faster.
Today, I'll share what feature flagging is
and why it's an important tool from development
through release.
You'll then see how to use feature flags in Remote Config
to launch a new feature with feedback from Firebase
Crashlytics and Google Analytics.
And I'll show you a new feature of Remote Config
that I'm really excited to share--
real-time config updates.
Let's get started.
Shipping new features to your users
is critical to your app's success,
and feature flagging helps you launch faster.
So what exactly is feature flagging?
Feature flagging is a method to dynamically update your app's
behavior and appearance.
It enables you to build new features
and hide in-development work, then gracefully transition
users to the new feature.
For example, you might use a feature flag
to hide a new user signup flow while you're developing it
or use a feature flag to transition
between API endpoints.
By dynamically updating parameters
in your app with server-side values,
feature flags enable you to decouple app version releases
from feature launches.
You can configure them to gradually enable
new functionality in the app and roll back that functionality
if there are production issues.
So why should you use feature flags?
We recommend them as an app development best
practice for a few reasons.
First, feature flagging reduces production risk.
No matter how much you test locally,
you know that bugs in production are real.
Because feature flags allow you to gradually roll out
new functionality, you can catch those bugs
before they affect most of your users.
If there's a bug in the app, you can quickly ramp down
the feature exposure to zero.
You don't need to release a new version of the app,
and users don't need to update.
Next, because you can use feature flags
to release new features to a subset of users,
you can gather feedback early.
You can use that feedback to iterate to a final product
you're confident your users will love.
You'll see in a minute how Remote Config's
powerful targeting tools can help further select which
users see your new features.
And finally, feature flags enable
teams to increase development velocity
by building and testing features incrementally
behind the scenes.
You can ship many small changes that add up to one
bigger feature.
Let's take a deeper look at how feature flagging makes
app development more efficient.
In a development cycle without feature flags,
feature releases are tied to app version releases.
There's no way to hide a feature once it's
in a released version, so you create a feature
branch in your code base and keep it open
as long as feature development takes--
sometimes weeks, months, or even longer.
When the feature is finally complete,
you merge in the feature branch and release your app.
The feature itself is finally launched when the user
downloads the new version.
The feature branch model seems intuitive
when you're releasing new features in the app versions,
but it has plenty of downsides, particularly
on a multiperson development team.
Feature branches require constant maintenance
to keep up to date.
They decrease collaboration and shared infrastructure
because they encourage isolated feature work.
And they create larger changes that are harder
to review and merge, especially when multiple features are
landing in a single release.
On the other hand, in a feature development cycle
with feature flagged releases, feature code
can be merged and even released in an app version
without being exposed to users.
You hide the work behind a feature flag
and launch the feature by enabling
the flag independent from any app version.
In this development model, long-lived feature branches
are replaced by small, incremental changes
that are quickly merged back into the releasable branch.
The short-lived nature of branches
means they're never out of date.
Collaboration is encouraged because the team is working off
of a common code base, and changes are easy to review
and usually trivial to merge.
Moreover, when multiple features are developed concurrently,
as is often the case, they can be
tested against each other along the way
so there are no surprises on release day.
If you're intrigued by the power of feature flagging,
you might ask how you'd implement it in your app.
Firebase Remote Config can help.
Remote Config is a Cloud service that
enables you to configure your apps without releasing
a new version.
Here's how it works.
You create key value pairs called parameters,
where you set values on the server side
and have in-app defaults to fall back to in case
of network connectivity issues.
This is how that configuration might
look if you're creating a feature flag
parameter in Remote Config.
The feature flag is a parameter named new_feature_enabled,
and this serves as the key in the key value pair.
The values that you set on the server
can be different depending on each user.
In Remote Config terms, these differences
are evaluated based on conditions.
For example, you could use a platform condition
to give Android users a green Android icon
or use a new users condition to give those users
a special welcome message.
For this feature flag, you choose a random percentage
condition and an app version condition
to enable the feature for 1% of users
who are on version 2.7.1 or greater,
since that's the first version where
your feature is ready to ship.
For everyone else, new_feature_enabled
has a default value of false.
You can set an in-app default value of false as well.
The Remote Config SDKs enable you to retrieve values
from the server and use them to override the in-app defaults
to change functionality.
You refresh the values from the server
occasionally, typically when the app is launched.
At least, that's how you refreshed values until now.
I'm excited to tell you that, today, you can get
real-time updates in your app.
This means that as soon as you publish parameter keys, values,
and conditions on the server, they're updated in your app
so your users always have the latest configuration.
Combining the power of real-time Remote Config updates
to configure your app with real-time feedback
from Firebase Crashlytics and Google Analytics,
you're able to launch features quickly and confidently.
Real-time Remote Config updates are exciting.
You might be wondering, how do they work?
And how do I use them?
Let's walk through an example of how
you can use real-time updates to launch
a new feature in a real app.
Users love the variety of recipes in your iOS app
FireRecipe, but your team has gotten lots of feedback
that the recipe times aren't accurate for all skill levels.
You and the team are launching a more intuitive recipe
difficulty feature to help everyone, from beginners
to pros, pick what to cook.
While developing the recipe difficulty feature,
you don't want your users to see your development work,
as it will probably confuse them and disrupt their app
experience.
Plus, there are a few bugs you need to fix.
So you want to put this feature behind a feature flag.
To do so, you'll open the Firebase Console
and go to Remote Config to create a new parameter called
enable_recipe_difficulty.
Give it a description and a default value of false,
then save and publish.
Now that the flag is set up on the server side,
let's see how to use that flag in your app code.
You are already set up with Firebase in your app.
And in case you aren't, check out the link
in the video description.
Then, you can use the Remote Config iOS SDK to fetch
and activate the values from the Remote Config server.
Fetch retrieves the server-side values,
and activate makes those values available to use in the app.
It's often convenient to call them together,
but you can call them separately, too.
After calling fetchAndActivate, you
can use Remote Config's Realtime API
to add a listener for new server-side values.
Behind the scenes in the SDK, adding a listener
opens a connection to the Remote Config backend.
As soon as a new version of the app is published,
the backend sends a signal to the SDK,
which will automatically fetch the new config values.
Multiple listeners will reuse that same connection.
addOnConfigUpdateListener's completion
is called whenever parameters from the latest published
version on the Remote Config server
differ from the ones currently activated in your app.
In case of any errors, add a guard here.
And if your feature flag parameter has been updated,
call activate to make the latest parameter values
available to use in your app.
You can use activate strategically
in your app to avoid surprising users with any unexpected UI
changes.
You've now gotten the value from the Remote Config server,
but haven't actually used it anywhere.
To do so, in your view, use the parameter
named enable_recipe_difficulty to access the Boolean value
and use it to conditionally look up the recipe difficulty
and display its new label instead of the one
for recipe.time.
Now, whenever the view appears, it'll
be updated with the latest flag value.
With this flag wired up in your app,
you can finish the development work on the recipe difficulty
feature without impacting your users,
even if you ship the feature code in some app versions.
But since the feature flag is false by default
right now, how can you and the rest of your development team
see the feature working while you build and test the app?
You can use Google Analytics user properties,
which are per user key value pairs
assigned with the analytics SDK.
User properties describe the users of your app,
and you can set custom properties
to fit your app's needs.
For example, you can set a user's favorite food
to pancakes.
In your app, if it's being run in development mode,
set the user property development_user to true.
Then you'll want to set the feature_flags value to true
for developers.
Open the Firebase Console to set the value
and run your app to check that it takes effect.
Edit the recipe difficulty property,
and create a new conditional value.
Create a condition and call it FireRecipe Dev Team.
You'll want it to apply when the user property development
user equals true.
When the condition is met, set the feature flags value to true
so the team can test the feature.
Save and publish the new value.
In the FireRecipe app, notice the feature time
is still visible, since you don't want
the UI to change unexpectedly.
But as soon as you navigate to a different view,
the new recipe difficulty is displayed.
After lots of iteration and testing,
you're finally ready to launch the new recipe difficulty
feature.
Let's walk through how.
First, you want to make sure the app is stable
and the version with the feature you're about to launch
is sufficiently adopted.
Stability enables you to easily identify
issues in the new release and focus
on fixing one bug at a time.
Sufficient adoption enables you to gather enough feedback
to quickly identify a successful or buggy launch.
Let's say you're ready to launch this new feature on version
1.1 of the app.
You'll first want to make sure that version
is stable and widely adopted.
To check, you can go to Analytics in the Firebase
Console and look at the Latest Release page, which
shows the percentage of users on the latest version
and that version's percentage of crash-free users.
There, you can see that the version
has been adopted by 86% of users and has a 100% crash-free users
rate.
Since your app is stable and the version with the recipe
difficulty feature has been well adopted for some time,
you're ready to start exposing users to your new feature.
You'll want to increase exposure gradually
to understand if the feature is successful without impacting
too many users if there are issues.
A ramp up of 1%, 10%, 50%, 100%, with a couple
of days in between each step, is a common practice.
But the exact steps and waiting time
will vary depending on your user base.
To set this up, let's go back to the Firebase Console
to start the release.
So far, we've been looking at the Parameters page
within Remote Config.
You'll need to create a new condition for the users
to whom you want to expose this feature,
so go to the conditions page to create one
for this feature flag release called
Recipe Difficulty Percent Release.
For the targeting conditions, select
user in a random percentage and 1% of users,
since that's where you'll start your release.
There are a few work-in-progress iterations
of the feature in older versions,
so you should select a minimum app version
as a targeting condition too.
That will avoid exposing the unfinished work.
To target a minimum app version, first select an app,
since versions are app and platform specific,
and then add a version condition using the greater than or equal
operator for version 1.1.
After creating the condition, go back to the Parameters page,
edit the existing parameter, and create a new conditional value
for the feature flag by selecting
Add New and the condition you just created.
You want the feature flag to be enabled for these users,
so assign a value of true and hit Save.
Since you configured a real-time Remote Config
listener in the app, as soon as you publish changes,
the Remote Config SDK will automatically
fetch this latest value and enable it for 1% of users.
The feature is now live, and users are interacting with it.
You can keep an eye on how it's doing in the wild
by monitoring stability and key metrics.
This way, you'll make sure the feature lands successfully.
One of your key metrics is daily active users,
so you want to make sure users don't drop unexpectedly.
To monitor this key metric, you can
take a look at the real-time analytics dashboard
to check that active users in the app are stable.
Looking good so far.
For stability, check Crashlytics, which analyzes
crashes in real time as well.
And it looks like there might be something up.
There's a crash coming from the recipe difficulty
class affecting users on version 1.1,
the version you just rolled out to.
You thought you'd fixed this in development,
but there must still be a bug.
To stop the app from crashing for your users,
jump back to Remote Config, flip the feature flag back to false,
and publish the updated parameter values.
Since you're listening for real-time config updates
as soon as you publish, your users are back in a good state.
Now that the app is stable, you can debug and release a patch
version before rereleasing.
With the feature successfully launched and landed,
let's recap what we covered today.
We first dove deep into feature flags,
how they improve the app development cycle
and mitigate risk launching.
We saw the excitement of real-time config updates
and how they enable smooth feature
launches and quick rollbacks when there are issues
so users' apps aren't crashing.
Finally, we powered that feedback loop in real time
as well, with metrics monitoring in Google Analytics
and stability in Crashlytics.
As we've seen, feature flagging is an incredible asset
in the app development toolkit, enabling
you to move faster and launch confidently.
Remote Config makes it easy to adopt the best practices.
And real-time updates create the best user experiences.
I'm really excited that the Realtime API is available today
for the iOS and Android SDKs and, most recently,
for game developers in the Unity and C++ SDKs.
Thanks so much for joining me today,
and I hope you enjoy the rest of I/O.
[MUSIC PLAYING]