There’s an additional challenge, though: updating code in the Apple App Store or the Google Play Store can take weeks. Imagine you built and deployed a new feature in React Native to the app stores and you discover a significant problem after the fact. Waiting two weeks (or more) for an update can quickly sour your user base on your app. That’s where feature flags come in.
Feature flags are a way to control who has access to a feature and when. You could enable a feature only for an internal set of testers and then maybe expand to an external beta tester group and eventually enable the feature for everyone. If something goes wrong with the feature, you can hit the “big red button” — a kill switch that instantaneously disables the feature for everyone. All of this is like a remote control for your app. The feature is in production and in the app stores. We call this “testing in production”.
In this post, I show you how you can test in production using Split’s shiny new React Native SDK. Split is a platform to configure and manage feature flags and to monitor performance as well as alert for any anomalous behavior. First things first: create a free Split developer account.
Getting Started with Feature Flags
Sign up for a free Split account, if you do not already have one.
Once you’ve logged in to your Split account, click DE in the upper left. Split has a notion of workspaces and you can have more than one. When you first create an account, a default workspace is provisioned for you and that’s what the DE stands for. Toward the bottom of the workspace popup, click Admin Settings (underneath your organization name). Click API keys. Notice that a number of API key types have already been allocated for you. When you create an account, A set of server-side and client-side keys are allocated in each of staging and production environments. You can have any number of environments and any number of API keys within those environments, but these are sensible defaults that cover most use cases.
A client-side API key has less privileges than a server-side API key and is suitable for any “public” type of application. This is the browser, mobile and desktop type of apps, which is what we’re focused on in this post. They’re called “public” because you don’t have any control over the environment they are run in. It’s easy for hackers to search a binary app payload for significant strings, like API keys. Thus, it’s safer to use a less privileged key in these environments.
Copy the Client-side Prod-default API key and save it somewhere for later use when we dig into the code.
The next order of business is to create some feature flags that we exercise later on in the code.
On the left nav, click Splits. Splits are synonymous with feature flags. Click “Create split”. Give it the name: profile_feature, set user for the Traffic Type and click Create. Congrats! You’ve created your first split. Without targeting rules, it’s not terribly useful however. Targeting rules determine how (or if) the feature will be available to the individual user. The individual targeting rules are called treatments. Click Add Rules. This immediately brings up a page with a lot of options. This is because you can have any number of treatments for a feature flag and lots of different rules for how those treatments are used. For now, we’re going to accept the sensible defaults. That is, there are two predefined treatments:
off and the default rule is
off. Click Save changes. Whenever you make a change in Split, you’re presented with a confirmation screen. This shows you all the elements that have changed in a diff style of additions and subtractions. Scroll down and click Confirm.
Create one more split (with the default treatments) using the above steps. But, call this split: about_feature.
The scenario we going to examine in code shortly is that you’ve added some new features to your app to show a user’s profile and to give information about the app. You’ve deployed these new features to the app store already, but you want to control who can see the new feature for a controlled rollout. Initially, most of your new users would NOT see these new features. But, when you’ve completed your testing in production, you will “flip the switch” in Split and everyone will have the new features available without you having to make a new release (and wait weeks for it to show up in the app stores).
React Native With Feature Flags in Action
The code for this post can be found on Split’s official React Native example GitHub repo here.
Clone the repo and open the project in the editor of your choice. I use Visual Studio Code.
Prerequisites for Running the Example Code
In order to get started you need one or both of the development environments for mobile applications. While you won’t need to deal directly with these tools, React Native does use their tooling to build and run your code.
For iOS, you need to have a Mac and Xcode developer tools.
For Android, you need to have Android Studio. NOTE: You need to have at least one emulator installed to test the code with Android.
The example app was created using the expo-cli tool. This tool makes it easy to work with your app locally and to prepare your React Native apps for publication in the app stores. In this post, we’re going to build the app from scratch, so you need this tool.
The following sections outlines building the app from scratch, but you can use the GitHub repo) as well if you want to just follow along. Let’s start building!
Bootstrap React Native With Split
Here’s a little taste of how we work with the React native app locally:
From the command line, I create a barebones project. From the project folder, I launch expo which in turn launches a handy web interface. From the browser, I can launch both the iOS simulator and the Android emulator with the application in its current state. Both will respond to application changes as we make them.
To begin, execute the following:
Choose blank and hit enter. This will create an empty project and install initial dependencies for you.
Next, execute the following:
This installs the Split SDK dependency to the app (unused for now) and launches the developer tools in the browser. From there, you can launch the iOS simulator and the Android emulator.
NOTE: You don’t have to launch both, but throughout this post I will use both to demonstrate the “write once, run anywhere” concept of React Native.
At this point, you should be in a similar state to the image shown above.
Update the App To Integrate Split
From the previous commands, we’ve already installed the Split SDK dependencies. Now, we’ll add the code that uses it.
Let’s grab the React Native example from Split and copy over the code and assets. In a new terminal window, execute the following:
These commands clone the official Split React Native SDK example into a folder next to the one you generated earlier. Then, key elements of the code are copied over. All this can be done while expo is still running.
App.js file in the editor of your choice and replace with the api key you copied earlier in the post. Save the file. Back in your terminal window where expo is running, hit the r key to reload. Now, you should see that every 3 seconds, the app pulls in state information about a random feature flag from the list of feature flags in your account. If you’ve followed this post to this point, you should see information for the
about_feature feature flags you created earlier.
NOTE: When running your app in debug mode on an Android device or emulator, you might get a warning notification stating that “Setting a timer for a long period of time is a performance and correctness issue on Android”. Because of how JS timers are used by the SDK, it is completely safe to ignore or hide this warning.
Notice that the treatment value is always
off. That’s because we left that as the default treatment. Back in your browser where you’re logged into your Split account, let’s update the behavior of these feature flags.
Click Splits on the left hand nav. Click about_feature. Scroll down and in the Set the default rule section, change the value from off to on. Click Save changes. Notice the diff and click Confirm.
The next time the app updates and the
about_feature feature flag is chosen, you should see that the treatment is now on:
This is a good place to look at the code to really see what’s going on. Then, we’ll go over some more feature flag settings and their impact on the app.
Toward the top of
App.js, you can see where we’re importing the
This looks pretty straightforward. Behind the scenes this statement is taking advantage of Split’s modular design for SDKs. Only the objects that are necessary for your app are being brought into scope. This keeps your binaries more compact, which is especially of concern on Android.
Take a look at the
_initSdk function (I’ve omitted part of it here for brevity):
Here, we’re instantiating the
SplitFactory with a configuration that includes your API key. Then, we use the factory to obtain access to the Split client and the Split manager. It’s the Split manager that allows us to get a list of defined feature flags. Take a look at the rest of the
There’s a lot going on here, so let’s break it down. First, the Split SDK has an event driven model. We don’t want to use the client or the manager until we’re sure that it’s ready. Therefore, we add a listener on the
setInterval function to execute another function every 3 seconds.
The meat of what gets executed is the following:
Get a List of Feature Flag Names
Choose a Name From the List at Random
Obtain the State of the Chosen Treatment
Display the Chosen Treatment Name, Its State, and the List of Feature Flags in the App
More Advanced Feature Flag Settings
Let’s say you’ve discovered that your new
about_feature is causing app crashes or an unacceptable amount of latency in the app. Before this becomes problematic, you can easily trigger the kill switch, which disables the feature for everyone.
In your Split console in your browser, click Splits on the left navigation and click about_feature. Click the red Kill button in the upper right. Type KILL in the form field and click Kill to confirm. Back in your Android Emulator and iOS Simulator, you should see that the
about_profile feature shows up as off.
Let’s say that you want to test in production in a controlled way. You can ramp up who sees the new feature and monitor the results. Assuming all goes well, you can keep ramping up on a percentage basis until you arrive at 100%
on, at which point all users would see the new feature.
In your Split console in your browser, click Splits on the left nav and click profile_feature. Scroll down to the Set the default rule section and choose percentage from the serve dropdown. Set
on to 90 (which will automatically set
off to 10). Click Save changes and Confirm. Back in the iOS simulator and Android emulator, you should likely see that the
profile_feature is now
on. However, if it still shows
off, it’s not an error. It just means that you landed in the 10% bucket that Split randomly created.
What’s Next with React Native and Feature Flags
I hope this whirlwind tour of Split’s React Native SDK and feature flags, in general, has been useful to you. It’s exciting to be able to take the skills you already have and instantly become a mobile developer! And with feature flags, you don’t have to fear the slow update cycle of the app stores. Release and test in production the Split way!
There’s a lot more you can do with Split, including monitoring, alerting, and experimentation. Here are some resources that you may find useful:
- Feature Monitoring in 15 Minutes (code tutorial)
- Respond quickly to degradations in metrics with alert policies (blog)
- Essential Guide to Experimentation