Feature flags are a tool used to add features to an app that should only be available to a subset of users. Feature flags are a great way to gradually see how new features will behave in a production environment, especially if an application is already being used by users in production.
This article will go over:
- How feature flags work
- How feature flags can be used to gradually test out features in production
- How feature flags are useful for trunk-based development workflows
How feature flags work
Feature flags are usually managed in some sort of admin interface where you can choose which features should exist behind a feature flag and which people should have access to those features.
Once feature flags are set in the admin interface, the feature flags settings can be recovered and then used within an application's API or web application to decide what block of code should be run (and hence which feature should be made available to a user).
As an example, say you are re-implementing the look of a "profile page" in your app. You could have a feature flag named
profile-v2 and associate that feature flag to user accounts with certain email addresses. Anywhere in your application code, whether it's your API code or your UI code, where you are adding changing the look or functionality of the profile page, you can check if if the currently authenticated user has the
profile-v2 feature flag enabled. If the
profile-v2 feature flag is enabled for the current user, then execute the new profile page code, otherwise serve up the old code.
Ideally, code behind feature flags is lazy loaded since it doesn't make sense to load code that a user will not be able to execute.
There are feature flag services available that provide the admin interface used to manage feature flags and also an API that can be called to get feature flags available for a particular user. Here's a list of some feature flag services:
If you'd rather not use a 3rd party service to manage feature flags, you could also build out your own feature flag service without too much trouble. A custom feature flag service might work as follows:
- In a feature flag admin page (that you could build out with a front-end framework), create a feature flag and specify which email accounts (or user IDs) should have access to that feature
- The feature flag settings are saved in a database
- When a user comes to visit the application, it will trigger an API call on initial app load that will request the feature flags enabled for that user
- The API will read the feature flag settings from the database and see if the currently authenticated user, which can be figured out via a JWT cookie or something similar, has access to the feature flag.
- Once the API determines which feature flags a user has access to, it will pass a list of feature flags to the front-end that correspond with the features the current user has access to
- The UI will conditionally display new features depending of whether a user has the feature flag corresponding with the particular feature
Feature flags can also be used on the server side if you'd like to prevent certain API functionality. For example, if you introduce a new API route related to a new feature, then you could check if the user that is calling the new API route has access to the new feature before trying to return/resolve data.
Gradually test features in production
Feature flags open up the possibility of shipping features to a production environment even if the feature is not completely finished or polished. This has the following benefits:
- Allow internal teams the chance to test out features with production data
- Allow iterating and testing features without negatively impacting normal app users
- Gradually rollout new features to users
A gradual rollout could be done by enabling feature flags to a set of beta users that sign up for your application's beta program. A percentage rollout is also another way to gradually rollout new features to users by gradually moving from 0 to 100% of users that can view a feature.
Unleash, an open source feature flag management system, follows the following process to handle gradual rollouts:
- Identify a unique identifier that corresponds to a user (e.g. a user ID)
- Pass the unique identifier to a hashing algorithm
- Normalize the hashed value to a number between 1 and 100
- If the normalized value falls within the percentage rollout, then the user will have the feature flag enabled
The above strategy ensures that users that are within the first 10% of a rollout with also be among the first 20% of users. This ensures that users also get the same experience even while the rollout percentage keeps increasing up towards 100%. You can find the code that Unleash uses for their normalization here.
Trunk-based development with feature flags
Trunk-based development is a source control / git strategy that revolves around developing features on short-lived feature branches that get merged into a main/master branch (also referred to as the trunk).
Feature flags help make trunk-based development more feasible since developers can create many small PRs that build upon a new feature and only have the feature accessible to all users when the feature is fully complete.
If feature flags were not being used in a trunk-based development workflow, every PR that introduces new features would likely be very large because it would have to include all the code to make the feature fully functional. Large PRs are difficult to review and are more likely to introduce bugs.
Personally, trunk-based development is my favorite way to manage projects in source control since you don't have to deal with a ton of different branches (e.g. development, staging, release-1.0, release-2.0, etc) and complicated merging and deployment patterns.