Delivering business value in small increments is the underlying tenet of continuous delivery. It requires a release cadence and a well-oiled machine with automation capabilities to periodically release value.
However, the ability to perform releases quickly is not enough. For example, it may take weeks, months or even years for a software development and architecture team to decompose and restructure a large, monolithic architecture system. Under such circumstances, a single release sprint won't be enough to demonstrate usable value to end users and business stakeholders.
Ideally, a system should incrementally evolve behind the scenes without radically changing end-user behavior before the exact, desired functionality is dialed in. Developers achieve this using feature branches, where features are developed in isolation and rolled out once they are fully built and thoroughly tested. The trunk (also known as a "mainline") is merged periodically to control the code drift and slowly introduce the new functions to the core application. In such a scenario, functional feedback may get deferred until later in the development cycles or only get partially reviewed until the branch is completely merged with the entire trunk.
The feature branch approach is complex enough with a single feature, let alone multiple features that deploy and run parallel. However, feature toggles represent a modernization approach that might be able to control what could otherwise become a chaotic ecosystem of mismatched features and redundant functionality.
Let's examine more about feature toggles, how they operate and the way they provide a simple, flip-switch approach to feature additions and release management.
How feature toggles work
A feature toggle is an architectural pattern that can help implement new features incrementally, without an explicit code modification or rewrite. All code changes route directly to the trunk codebase, but the system can still evolve without altering end-user experience until the transition is complete. The execution path for the feature may be controlled by one or more toggles. The rendering and execution flow are controlled in tandem.
In addition to controlling execution flow, feature toggles also regulate feature rollouts. It's possible to configure releases so that a new feature is only pushed to a limited subset of end users. Developers can categorize and target these user subsets as they see fit, whether it is based on geographical location, predefined user type or a random percentage of total users. This capability facilitates strategic deployment approaches like a canary release, which can minimize the impact of a detrimental change, refine A/B testing and provide targeted user behavior metrics.
An example of this approach would be placing identifying wrappers around a particular property-backed configuration. Applications can use these wrappers to evaluate the context of a situation and determine whether or not a feature should be enabled for a particular set of users. This enables a system to be tested with small user groups and observed for failures to prevent a disastrous rollout.
The application begins the process by reading disk-based configuration files to fetch and determine the conditional states that should activate one specific feature over another. During runtime, specific state configurations can morph through a data reload without needing to perform a total application restart. This can also work with a remote data store, such as a remote database, a private cloud or a cloud-based data management service platform.
There are multiple variations on this feature toggle design pattern, however, including the use of predetermined toggle values to guide an execution pathway, A/B user testing approaches and partial rollouts targeted at particular subsets of users. While these all involve relatively simple coding approaches, there are a number of open source feature toggle tools equipped to cater to the requirements of larger, more complex application environments, such as Unleash, Flipper and Flagr.
Pitfalls of feature toggles
It's easy to get carried away with feature toggles. An unchecked collection of toggles introduces numerous execution paths to keep track of, which can quickly spiral into a maze that is excruciatingly hard to test and manage.
Keep the number of toggles you use in check and identify each one carefully. For instance, separate the toggles you want to keep in the long term from those that are related to temporary bug fixes or experimental features. For instance, a toggle may be tasked to operate and configure a multi-tenanted service environment, which is a more permanent fixture. Temporary ones, however, may only serve the purpose of incrementally evolving a legacy application's features. These temporary toggles need to be cleaned up once they've served their purpose, lest your software system become infested with confusing stacks of old, useless toggles that simply take up space.
Finally, the names used to identify toggle properties should be consistent and follow an established naming convention. Ideally, start by creating a simple feature name, then track the variable boolean's "on" and "off" states to identify whether the toggle is enabled or not.
Avoid using action-oriented verbs in a toggle's name, as this may only serve to confuse readers as to what specific feature the toggle actually controls. For instance, names like "enable_new_toolbar," "disable_old_search_bar" and "activate_nicer_buttons" might not be as simple to understand at a glance as something like "new_toolbar," "new_search_bar" and "nicer_buttons."