How-To's

Feature Flags: What They Are and How to Use Them

Feature flags

JetBrains Space is an all-in-one solution for software projects and team communication. Space is Software-as-a-Service (SaaS), so there’s no need to maintain your own installation: you’ll get new features immediately when they are made available.

But here’s a secret: new features are deployed to production long before they become available to everyone. Instead of big and risky deployments, we use feature flags to enable functionality when we’re ready.

Many developer teams have at least heard of feature flags, and some may have experimented with them. In the Space team, we rely on feature flags to bring new and updated functionality to our customers.

In this blog post, we’ll see what feature flags are, what benefits they bring, and how the Space development team is using them to deliver new functionality and gather feedback more quickly.

What are feature flags?

Feature flags, also known as feature toggles, are used in software development to enable or disable functionality without having to deploy new code. You can compare them with an `if` statement that checks whether a code path should be available or not.

Let’s say you wanted to redesign the code reviews feature in Space. Ideally, you want to be able to deploy it to production as soon as possible, and collect feedback from a small subset of users. Instead of building this in a separate branch, and deploying to some pre-production environment, you could build the feature and deploy it to production as soon as possible.

Everywhere the feature would surface in the user interface or business logic, there will be an `if` statement to check if the feature is available to the current user:

if (featureFlags.IsEnabled("code-reviews-new-ui", currentUser)) {
  // … show component in the UI …
}

Feature flags can be combined with other feature flags, or be more granular to let you toggle different parts of functionality that is under development:

if (featureFlags.IsEnabled("code-reviews-new-ui", currentUser) &&
    featureFlags.IsEnabled("code-reviews-new-ui-reporting", currentUser)) {
  // … show reporting menu item in the UI …
}

As an example in Space, a redesigned code reviews workflow is on our roadmap. Some of our internal users and Space Insiders already have access to it and can provide us feedback.

Space insiders

Space Insiders is a product community, a place where Space users and the development team keep in touch. Insiders can suggest improvements for the product, ask for help, and share use-cases and best practices. If you’d like to become a Space Insider and share your insights with us, please send your request to spaceinsiders@jetbrains.com.

Benefits of feature flags

A development team can adopt the use of feature flags for several reasons. Generally speaking, there are three benefits to working with them.

First, as we discussed in the introduction, feature flags let you gradually roll out new functionality for your users. By enabling a feature for some users, and keeping the feature hidden from others, you can get feedback from specific users. You can do A/B testing, and use a feature flag to improve UX for some users and see if that functionality becomes more discoverable (or not).

Second, time-to-production becomes shorter. You can keep a feature flag disabled for all users except the developer and the Quality Assurance (QA) team. They can test and fine-tune the feature before you roll it out to more users of your software. At some point, the feature may be deemed “production-ready”, and you can flip the switch for all your users. No need for a new deployment at that time!

Third, new features can be released even when they are not in a finished state. Developers don’t need to work with long-lived branches that become hard to merge over time. Instead, they can merge to the main branch often, making sure the feature is only available to those with the feature flag enabled. When a big refactoring happens in a code base, the new feature gets refactored along, reducing hard-to-resolve merge conflicts down the road.

How the JetBrains Space team uses feature flags

Space is a Software-as-a-Service (SaaS) offering, so every change that is deployed to our cloud is immediately available. In the Space team, we started to use feature flags because we wanted to be able to try out new functionality with minimal risk and minimal user impact.

When we started out, feature flags were only used on the client-side. We used them mostly to show or hide certain elements in the UI. We started adding mobile apps for Android and iOS, we built the IntelliJ IDEA plugin, and folks started integrating Space with its API. No longer did we have one user interface, all of a sudden we had multiple, so we had to expand our use of feature flags to the entire service.

Our feature flags are tightly connected to issues in our tracker. By doing this, we can track the entire lifetime of a feature, from design to development, testing, and deployment. Commits that contain a specific feature flag are linked to the issue, making it easy to follow updates and the current status of new functionality.

More importantly, linking feature flags to an issue means the flag has an owner. We can look at the feature flag, and find who is responsible for the feature and look at its description and design in our tracker.

How we develop new functionality

When we create new functionality, our design team steps in to help create or update user interface (UI) mock-ups. We use Figma to work on these: the tool lets us re-use existing UI elements and collaborate and comment on designs. The Figma design is also linked to the issue in our tracker, helping with an end-to-end overview of how a feature came to be.

Figma design mock-up of the time-tracking functionality.

Figma design mock-up of the time-tracking functionality.

Development usually starts in a separate branch, where a feature flag is added and new functionality is developed. Depending on the complexity of the feature, this branch may be deployed to an internal development stack to try and test things out.

When the developer is confident about the feature and automated tests are in place, they can merge it to our main branch. At this time, they may create some screenshots and a basic walkthrough of the feature. Very often, it’s also demoed to the rest of the Space team as well.

The feature flag and its related functionality is now en-route to being deployed to production!

The first stop is our own Space instance. At JetBrains, we do a lot of dogfooding. We use our tools and services ourselves before we ship to our customers. For Space, that means the first deployment of new functionality is done to our internal deployment of Space, used by all employees.

In this first deployment, however, new functionality and its feature flag are switched off by default. Most feature flags can be self-managed. The developer can enable it for themselves, and run some additional validation. The QA team and technical writers can also enable the feature flag and start working on documentation and samples.

Recently-released CalDAV support feature flag

Fun fact: we also have a chat channel where feature flags are announced, and we can see who inside JetBrains enables them. A good opportunity to gather extra feedback while dogfooding!

Next, the feature flag is enabled for everyone on the Space team, and after that, for everyone inside JetBrains.

When we’re happy with the feature on our internal Space, it is deployed to the Space cloud that is used by our customers. Also here, the feature flag is “off” for all organizations and users by default. Our QA team then enables the feature to do some smoke testing on their organization.

The feature may then be announced to our Space Insiders. They can use the new functionality, and discuss it with our team. When they are happy with it, and we are happy with it, the feature is enabled for everyone: all organizations and users in the Space Cloud. At this point, we also create a post in the #JetBrains Space channel of every Space organization.

Announcement of CalDAV support posted to every Space Organization.

Announcement of CalDAV support posted to every Space Organization.

What to look out for when adopting feature flags

The concept of feature flags is simple – it’s essentially just an `if`. This makes it a very powerful concept!

For Space, we can toggle features per user, per team, and per organization. Toggling is also real-time: there’s no need for you to reload the application. Our web- and desktop apps immediately update the UI when a feature is enabled or disabled.

But as we all know, with great power comes great responsibility…

Removing feature flags after go-live

At some point, a feature flag will have to cease to exist. If feature flags are kept around for too long, you’ll end up with feature flags being dependent on other feature flags, and … well, you get the picture. When you adopt the concept of feature flags, you’ll also need to think of a good process to remove them at some point.

In the Space team, we remove feature flags when we consider a feature as stable and see no more need for it to be available as a toggle. Since “it’s just an `if`”, this should be easy, right? Drop the obsolete code path, remove the surrounding `if` statement, and drop the feature flag.

Removing the old implementation is not always safe. In the past, we have had some feature flags that consisted of too many changes. When removing the old code for such feature flags, we ran into other feature flags that were still in use, or depended on code that was still needed. From these experiences, we learned that it’s important to keep feature flags granular, so you don’t replace the pain of large merge conflicts with another type of pain.

Deprecating unused features and their flags

Much like removing feature flags when a feature is considered stable, you’ll have to think about deprecating unused features. Feature flags allow for experimentation, and at some point you may have several features that will never see the light of day for customers.

We don’t have any rules for this in the Space team. Usually after there’s a consensus in the team, the original developer of the feature will deprecate the feature flag and related code paths.

Testing with feature flags

Another aspect is testing. Do you need to test all possible combinations of feature flags? Or just the ones that make sense? But which combinations make sense?

In the Space team, we look at this on a case-by-case basis. Usually changes related to a feature flag ideally are granular, and keeping tests for the original code path and adding tests for the new code path is sufficient.

Conclusion

If your team is building Software-as-a-Service, you may look into adopting the concept of feature flags in your development and release process.

Feature flags so far have been working well for us. While we still use branches for initial implementation and more risky changes, they are merged more quickly and more often, reducing the pain of merge conflicts.

Feature flags also let us deploy new functionality to production and only enable it for certain organizations and users. This helps us collect feedback about a feature early on, and lets us polish it further before we make it available to a wider audience.

image description