Hello Firebase Developers!
We recently launched a major refresh for the Remote Config SDK in our v2 release, and it includes a few changes that will help you keep your app responsive and snappy.
The tl,dr; is that in the v2 SDK we’ve improved Remote Config along the following themes:
- Faster startup times and smarter fetching
- Improvements to communication between the client SDK and RC backend
Read on for more details on each of these new updates!
Faster startup times and smarter fetching
One of the biggest requests we’ve had is to add non-blocking initialization and fetch calls for Remote Config params, and for good reason.
Let’s say you’re a developer for a travel app, and you want to show a travel deal based on whether a customer is predicted to spend on hotels at some destination (possibly using Firebase Predictions). With Remote Config, you can surface such travel deals to just those users. Now, let’s say that these deals are surfaced alongside the main parts of your app, where your users find and book travel. What you don’t want is for your users to have to wait for these main parts of your app to get blocked on Remote Config initialization for those travel deals. With the v1 SDK, unless you were very careful about where you placed your Remote Config initialization call, your users would have to wait for Remote Config initialization before being able to use the main parts of the app. In the v2 SDK, this is no longer the case.
By introducing non-blocking initialization, it is now possible to load Remote Config without affecting the load time of the rest of the app. This can improve startup times across the board, but is especially important for users who are in regions of limited or slow network connectivity.
We’ve also added a new convenience method in the V2 SDKs to both fetch and activate your Remote Config values in a single call, which streamlines the activation code flow. Here are how the new calls look for fetching and activating Remote Config parameters before and after the v2 SDK updates:
iOS
(Before)
// BLOCKING
remoteConfig = RemoteConfig.remoteConfig()
// Fetch with a completion handler.
remoteConfig.fetch { status, error in
if status == .success {
remoteConfig.activateFetched()
let value = remoteConfig[“myKey”];
}
}
(After)
// Non-blocking initialization.
remoteConfig = RemoteConfig.remoteConfig()
remoteConfig.fetchAndActivate { (status, error) in
if status == .successFetchedFromRemote || status ==.successUsingPreFetchedData {
let value = remoteConfig[“myKey”];
}
}
Android:
(Before)
// BLOCKING
FirebaseRemoteConfig frc = FirebaseRemoteConfig.getInstance();
frc.fetch()
.addOnSuccessListener(new …<>() {
frc.activateFetched();
readFrcValues();
});
void readFrcValues() {
value = frc.getInteger(“myKey”);
}
(After)
// Non-blocking initialization.
// Loads values from disk asynchronously.
FirebaseRemoteConfig frc = FirebaseRemoteConfig.getInstance();
frc.fetchAndActivate().addOnSuccessListener((unusedVoid) -> readFrcValues());
void readFrcValues() {
value = frc.getInteger(“myKey”);
}
Another important update for smarter fetching is the introduction of the new FetchTimeoutInSeconds
and MinimumFetchIntervalInSeconds
parameters, which can be used together to provide smarter fetching policies for your app.
The FetchTimeoutInSeconds parameter is useful when you don’t want your application to wait longer than X seconds to fetch new Remote Config values. It sounds like a small change, but this can actually make a considerable difference in how you build a responsive app for your users.
For example, let’s go back to the travel app. The travel deals portion of the app is conditioned on Remote Config values, but this is for a non-critical part of the app. It doesn’t get in the way of the main booking flow in the app, so it’s not as important if the travel deals load up and show immediately after the user opens the app.
Now let’s say we’ve designed a new booking flow for our app, and want to roll it out to a test group to get some feedback. In this scenario, users will need to wait for a network roundtrip to the Remote Config backend to determine if they’ll get the new booking interface for the test group, or the current booking interface instead.
Waiting for one roundtrip for the interface to load isn’t generally a huge deal, but what if our user is in an area of limited or spotty connectivity? In such cases, the reliability or availability of network infrastructure can dictate the user experience we can provide.
This situation is where being able to set the FetchTimeoutInSeconds becomes really useful. Let’s say we don’t want the test group to experience any Remote Config fetch delays greater than three seconds. Well, using this parameter we can specify exactly that. So if our user does happen to be in an area with spotty network connectivity, we can still ensure they can have a great experience by falling back to either the previously fetched values or the default values.
The new MinimumFetchIntervalInSeconds parameter, as the name implies, allows you to set the minimum interval for which you want to check for any new Remote Config parameter values.
The new parameter name better describes how Remote Config handles retrieving new parameter values from the RC backend over the previous caching terminology, but does not change how Remote Config handles caching. If the default minimum fetch interval of 12 hours is too long for your app’s needs, you can adjust it to a value that’s more appropriate for your app, such as once per hour.
Keep in mind that going beyond that might cause your app to run into rate limits. In case you do hit a rate limit, though, the new error response codes can help deal with that (read the section below for more details).
Setting up these new parameters is straightforward. On Android, you can set both the minimum fetch interval and the fetch timeout parameters directly with the Settings Builder API:
Android
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
.setMinimumFetchIntervalInSeconds(fetchRefreshRate)
.setFetchTimeoutInSeconds(fetchTimeout)
.build();
mFirebaseRemoteConfig.setConfigSettings(configSettings);
On iOS, you can set similar values on the configSettings
object.
iOS
let remoteConfigSettings = RemoteConfigSettings()
remoteConfigSettings.minimumFetchInterval = 1200
remoteConfigSettings.fetchTimeout = 3
remoteConfig.configSettings = remoteConfigSettings
To enable development mode using the new MinimumFetchIntervalInSeconds
parameter, just set the parameter value to 0. Just be sure to set this back before you ship to production!
Improvements to communication between the SDK and RC backend
For the Android SDK, we’ve updated how the client SDK communicates with the Remote Config backend. The Remote Config SDK’s previous implementation sometimes resulted in error responses getting eaten up along the way. This would sometimes make it difficult to understand why fetch requests were failing. Providing more informative and meaningful error messages is now improved by replacing networking calls through direct REST API calls to the Remote Config backend. So you’ll now be able to get more meaningful error responses when something goes wrong.
How to upgrade
Upgrading is easy! Just update your Remote Config dependencies to the latest version, rebuild your app, and you’ll be set up to use the latest Remote Config V2 SDKs.
Let us know what you think!
We’re always trying to improve and make Remote Config, as well as each of our other Firebase products, more helpful and easier to use. These changes are an effort towards that, so let us know what you think about them! Also, if you discover any bugs with the new updates, we’d love to hear about those too. Please reach out to us on StackOverflow or the official Firebase support site.
And one more thing - we’ve gone open source
That’s right, the Android SDK and the iOS SDK for Remote Config are now both open source! You can check out the GitHub repo for the Android SDK in all its open source goodness here, and the repo for the iOS SDK here.