Use Feature Flags to Release Often

Written by David Raffauf

At UserTesting, we don't like stale code rotting in pull requests. But what are we to do when we have code that isn't ready for all of our customers to see?

The longer we wait to merge code, the more it diverges from our main line of development. Our code is rotting. The more code we hold onto like this, the scarier it is to merge. So how do we leap over all of these pitfalls? We use feature flags.

What are feature flags?

Feature flags are very simple. We create a flag for a specific feature that we’re developing. When it’s turned on for a customer, they can see the feature, otherwise they cannot. There are a few modes in which we can use a feature flag:

In our code and our tests we simply wrap code in a block that checks to see if the feature should be enabled. This allows us to deploy code to production and easily show or hide the functionality. Our test suites can test both scenarios: with the feature enabled and without the feature enabled. There are a number of use cases for feature flags.

Use cases

A/B Testing

As you might have guessed, we like A/B testing at UserTesting. Sometimes we have some changes, small or large, that we’d like to test with a small group of customers. We may start by testing out these features with a small group internally or with a group of customers who have expressed an interest in the feature. This is a perfect time to use a feature flag to gather data on how customers use an alternate version of a feature.

New features or versions

Developing a new feature or new version of a feature can take a long time. While we’re working on something like this, we like to feature flag it so that we aren’t diverging from our main line of development over time. Often our first commit of a new feature will be creating a feature flag. By doing this we can iterate on a feature until it’s ready and keep it in the main line of development.

Rollouts

Once we have features flagged, handling rollouts becomes much easier. We can simply add more and more people to our feature flag’s access list until we’re comfortable rolling the feature out to everyone. This allows us to collect customer feedback and to handle any performance or scaling issues.

Empowering product owners

Taking this approach also leaves the decision of when to do a release in the product owner’s hands. While it would still be a Product and Engineering Team effort to make sure the feature is ready for release, at any time a product owner could simply make the feature available. Or they could make it available for one more customer that’s interested in being a beta tester. If for some reason the product owner determines the feature isn’t working as expected, they can turn it off like a light.

Removing a feature flag

After a feature has been in use for awhile by all of our customers, we’ll remove a feature flag. This involves removing the flag itself and also the alternate branches in the code and tests where the feature flag is turned off. This leads to one of those rare pull requests that engineers love that are 100% code deletion.

What’s the downside?

An inherent characteristic of feature flags is that they add branching complexity to your code. If you’re able to make a decision early and avoid creating a feature flag, then you’ve saved yourself some work. The best kind of code is the code you don’t have to write.

Indefinitely postponing decisions

While flags are a great tool, they shouldn’t indefinitely postpone a decision on whether a feature is ready. There needs to be a clear expectation that the feature will eventually be made available or removed.

One way to keep the team honest is to agree on a date by which you’ll make a decision and remove the feature flag. It’s up to you how this is enforced but it could be as lenient as a calendar reminder or as punitive as a test that fails your build. We prefer to rely on good communication.

Implementation pitfalls

Feature flags could be implemented per user, per account, or even per subscription. When designing your feature flags, think about along which lines you would like to turn features on or off. If you choose to do it by account, do all of your users have accounts? If you choose to do it by subscription, do all users or accounts have subscriptions? You may need more than one way to support them.

Always be shipping

What we’ve really liked about using feature flags is it encourages us to think about how we can take a feature from planning to shipping. We don’t have holding pens where we build up new features that will one day be tested and released. The expectation is always that our code needs a path to being deployed.