Feature toggles (or feature flags) are a technique in software development for adding functionality in such a way that it can be turned on or off (toggled). Feature toggles fit well with the practice of Continuous Integration and Delivery (CI/CD) and with techniques like A/B testing and canary releases.
At Jet, we use feature flags to improve our products with speed and confidence. We phase in new functionality over time and measure the results — thereby reducing risk.
A simple example of a feature toggle
Super simple, right? While this example imports a static JSON file, the configuration should ideally be dynamic so that toggles can be managed independently from code deployments. Feature toggle configuration can come from many places, such as environment variables, request headers, query strings, or services like consul, Launch Darkly or the open-source tool, Unleash.
You might be inclined to dismiss feature toggles as too simple, but don’t be fooled—feature toggles have a wide range of use cases that can boost your team and products with the following superpowers:
One of the more obvious benefits of feature toggles is that they allow you to release new features that are still under development. Since each new feature is behind a toggle, it won’t go live until you decide to turn that toggle on. If you have a method of updating your toggles in production, development schedules can be separated from deployment schedules. The pain and risk of late night releases gets replaced with the click of a button that can happen at any time.
If you’re used to painful release processes, hidden features should already sound appealing to you, but there’s more! If you add the ability to enable features via a dashboard page or a URL query string, your QA or product team can verify that features behave as expected in production, with real data. You can also share features with users for feedback before making them live for everyone.
Feature toggles are especially useful for speeding up the development process when combined with Continuous Integration and Delivery. Rather than working on long-lived branches that become difficult to merge, work can be done in small pull requests that get merged frequently to the main code branch (or trunk). Developers are more productive, because merge conflicts are dealt with when the context of a change is still fresh in people’s minds.
Bugs can also be handled more efficiently with feature toggles. If someone finds a bug with a feature that’s behind a feature toggle, you can immediately switch off the toggle. Not only does this prevent the interruption and risk of rolling back changes, it allows new changes to continue rolling out to production so your pipeline stays fast and productive!
Our team once added support to an internal tool for a new feature called “Deals” that required changes to multiple services. Using a feature flag, we released our code to production before the feature was live in other services. Both the front and backend of our tool shared the same feature toggle service, so when the feature was ready, we flipped the toggle and the frontend UI and backend API updated at the same time. When there were subsequent rollbacks and re-releases, we simply flipped the toggle. Our workflow wasn’t disturbed by the release schedule and we continued shipping new features to production.
After you’ve felt the power of feature toggles combined with Continuous Integration and Delivery, you’re ready to enable even more abilities. Feature toggles are a nice way to ease into experimentation to test out ideas and learn what works best for your users.
On a recent internal project, we suspected that users were bailing out on a form early because they weren’t seeing all of the available options. Someone on the team had an idea for a simple change that might better fit users’ expectations. To test this idea, we implemented a feature toggle that switched two columns using Eric Elliott’s feature-toggle npm package. We shared links with users that enabled the toggle so they could experience the change with live, production data. We then collected feedback, determined the change was effective and made it live for everyone.
If you’re doing A/B/n testing, this process probably sounds familiar to you. If so, you might already be using feature toggles! A/B/n tests are a form of experiment where two or more versions (or variants) of a feature are served to users and the results are measured to determine which one performs better for a given conversion metric. The number of variants and amount of traffic the test receives determine the time needed to find a statistically significant winner.
A/B/n testing can be a large topic requiring complicated setups and data scientists to fully parse out the data and results, but with feature toggles you can start reaping some of the benefits of experimentation immediately. While Jet has its own in-house tooling to handle experimentation at scale, as a small team working on an internal tool, the feature-toggle package made it easy to start experimenting and validating assumptions without a lot of setup.
Once our team started using feature toggles to run experiments, an added benefit we’ve noticed over time is increased flexibility and innovation from a product perspective. Ideas for improvement don’t only come from the product or UX team, they come from engineers, too. Feature toggles make it easy to test assumptions and once people start seeing their ideas brought to life and validated, they feel more invested in the product and the process.
Conversations that might have lead to long arguments over heuristics in the past happen less frequently. “I don’t think that will work” gets replaced with “Let’s try it out”. Feature toggles help push the team culture towards embracing change, rather than shying away from it.
As a result, there’s less pressure to make things perfect the first time. When your team starts delivering work faster and trying out new ideas along the way, people start to notice. They develop trust that even if the first version of a feature doesn’t perform well, the team will learn and adapt. Trust and flexibility leads to team autonomy and (super)empowerment!
With great power comes great responsibility…
Now that you’re excited to fly off and fight painful release processes and inflexible product direction with your new-found powers, there are a few more things you should know. Feature toggles can be easy to implement, but they also require careful consideration. When used carelessly, they can pollute your codebase with many layers of conditional logic or expose vulnerabilities to malicious supervillians.
Don’t let the fear of technical debt paralyze you from unlocking the full potential of feature toggles. Use these practices to prevent the adamantium strength of feature toggles from poisoning your code base:
- Remove feature toggles after they are no longer needed
- Periodically review all feature toggles in use
- Implement the logic for each feature toggle in as few places as possible. Refactor, if needed, to reduce complexity.
- If a toggle requires code in several places, create a pull request to remove it before merging in the new toggle. That way the logic is still fresh in your mind, and the toggle will be easier to remove later.
Care should also be taken when implementing feature flags on the client-side (vs server-side), as client-side feature toggles can always be manipulated by an adversary. When in doubt, talk to your application security team to determine if a feature toggle poses a security risk.
Now go out and make the world safe with feature toggles!
Further reading & resources
- Feature Toggles (aka Feature Flags) by Pete Hodgson
- FeatureBranch by Martin Fowler
- feature-toggle an npm package by Eric Elliott that’s easy to get started with. It provides feature toggles using query parameters.
- Unleash an open source feature toggle system
If you like the challenges of building distributed systems and are interested in solving complex problems, check out our job openings.