Feature flags allow faster, safer feature delivery to users by decoupling code deployment from feature release. They provide a number of benefits to development and DevOps teams.
These include:
- enabling A/B/n testing,
- showing different experiences to different users and allowing teams to see how those experiences affect user behavior,
- enabling Kill Switches that allow for a feature to be turned off immediately if it’s not functioning correctly,
- and perform incremental rollouts or block users.
Feature flags also support continuous integration and delivery (CI/CD) practices because of simpler merges into the main software branch and by being able to push things into production live and still have the feature disabled until it’s complete. That said, in some organizations, developers may be kicking off test sequences and confusing QA folks when feature flags appear in the code, thinking it adds complexity and uncertainty as to what to test. To avoid this, development teams need to organize to enable effective use of feature flags.
In the O’Reilly ebook “Feature Flag Best Practices” Pete Hodgson and Patricio Echagüe, CTO and co-founder at Split.io, reveal several best practices for implementing feature flags into a development environment. While Echagüe allows there will be a slight learning curve, he points out the benefits of testing in production. In other words, conducting functional and performance tests with real-life traffic, systems, and data outweighs the learning curve. It’s difficult to test network latency or endpoint response time in a pre-production environment. Feature flags makes the need for a ‘production-like’ staging environment behind the firewall obsolete for QA teams, so they can go direct to test in the production environment for functional, performance, and UAT testing.
The fundamentals
From a functional standpoint, feature flagging is about software having the option to choose between multiple different execution paths, based upon a flag configuration, usually taking into account which user/runtime context is making the web request. The execution path is determined by a toggle router based on user/runtime context and flag configuration.
The ebook uses an example of an ecommerce site, acmeshipping.com. The site’s developers want to test whether users will be more likely to place an order if the “Place Your Order” button is enlarged and want to use feature flags to do the checkout flow A/B testing. They accomplish this by modifying the checkout page rendering code so there are two different execution paths available at a specific toggle point:
renderCheckoutButton(){
if(features.for({user:currentUser}).isEnabled(“showReallyBigCheckoutButton”)){
return renderReallyBigCheckoutButton();
}else{
return renderRegularCheckoutButton();
}
}
Every time the checkout page is rendered the software will use that if statement, which is the toggle point, to choose the execution path. It does this by asking the feature-flagging system’s toggle router whether the showReallyBigCheckoutButton feature is enabled for the current user/runtime context requesting the page. The toggle router uses that flag’s configuration to decide whether to enable that feature for each user.
Feature flagging systems provide developers with a way to configure a feature to support different targeting scenarios based on different business strategies like canary releases, dark launching, targeting by demographic, account, or license level. Once teams are familiar with its benefits, more use cases surface and usage grows.
Echagüe advises that maintaining a few best practices initially will make the task of getting up to speed with feature flags and how to use them easier. Several are listed in the ebook.
Maintaining flag consistency essentially means that if user A visits a site and the feature-flagging system decides that user A will see this feature (in other words, variation “on” of the feature), user A must then continue to see this same variation regardless of how many times the flag is evaluated.
Moving flagging decisions to the server creates a user-perceived performance bump. Modern web applications typically contain client-side logic. Developers usually have a choice between making toggling decisions client side or server side. Consider that single-page applications are already making a server-side call to render the data needed for the UI. If it’s configured so that a call is made to a feature-flag service, then one network call fetches all feature-flag evaluations with the server-side data.
Implementing flagging decisions close to business logic and scoping each flag to a single team are closely aligned given that they both support business outcome metrics, although to different teams.
Consider testability. It’s tempting to write tests for all possible combinations of flags. But it’s better to reduce the scope of the test to a few flags or isolate the test so the tester can test the main target flag with the rest of the flags turned on.
Run the feature flags tests in dev mode to avoid a connection to the cloud. This allows you to mock the behavior you want to test, with the feature on and again when it’s off. Do this during unit testing because it’s closer to the flag, and the tests will run faster in this environment. The point, according to Split.io’s Echagüe, is to test the leaves, not the tree.
Last, but not least, build a feedback loop. A mature feedback mechanism is incredibly effective in unlocking the maximum value of a feature-flagging practice. Making a change without seeing the effect of that change is like driving a car with a fogged-up windshield.
Following tips like these will help modern product delivery teams reduce risk, work with feature flags at scale, provide feedback mechanisms and help deliver a growing feature flag practice.
For more information, visit www.split.io.
Content provided by SD Times and Split.