As mentioned in the previous article, while introducing feature flags can provide significant benefits, there is a potential drawback of increased complexity in code and flag management.
In order to mitigate this complexity and effectively operate feature flags, we will talk about the following two topics.
- Practices for Code Implementation
- Practices for Operation and Management
Note: For practices that cannot be fully covered here, the articles on martinfowler.com can be referenced.
Practices for Code Implementation
Two practices are explained here to reduce code complexity using feature flags and make it easier to maintain and test. In addition to these practices, applying general programming design principles can also be effective.
Avoid inserting flags related to a single feature in multiple layers
A common mistake when implementing feature flags in code is inserting flags related to a single feature in multiple layers and, for example, inserting them in the front-end UI and back-end API layers during some feature addition.
In this case, there is a potential problem where the flag is on in one layer but off in the other layer, resulting in unintended behavior. Moreover, when removing the flag, it is necessary to remove it from all layers; otherwise, it can become a source of bugs.
To solve this issue, it is important to consider which layer to insert the flag when thinking about feature additions. As a basic strategy, inserting the flag in the topmost layer is desirable. This avoids the scattering of conditional branching through various layers based on the flag and makes it easier to pass user information or request information for flag value determination.
However, it is important to note that if you need to retrieve an endpoint from the flag for database migration, you may need to insert conditional branching based on the flag in the core part of the code, so it is not always necessary to place everything in the topmost layer.
When implementing code to switch between new and old features using feature flags, is recommended to separate the dependency on it from the areas where behavior switching is desired.
A simple example:
const client = getFeatureFlagClient();
function someFunction() {
if (client.booleanVariation("new-cool-feature", false)) {
showNewCoolFeature();
} else {
showOldFeature();
}
}
While this approach may work, it can be considered brittle to changes. For example, if you want to change the conditions under which a feature is turned on or switch the flag type from a simple on/off flag to an A/B testing flag, you would need to modify the code inside the logic.
As the use of feature flags increases, this means that the entire codebase becomes more dependent on the feature flag system. Additionally, directly depending on the feature flag system in the logic can lead to difficulties in proper mocking and writing unit tests.
To solve this issue, it is important to separate the dependency on feature flags from the areas where behavior switching is desired. By introducing an abstraction layer and making the logic depend on it, you can centralize the code related to the feature flag and its dependencies and improve the testability of the logic.
One example that could be considered is as follows:
function createFeatureDecisions(client) {
return {
isNewCoolFeatureEnabled() {
return client.booleanVariation("new-cool-feature", false);
},
// Other functions related to other features
};
}
function someFunction(featureDecisions) {
if (featureDecisions.isNewCoolFeatureEnabled()) {
showNewCoolFeature();
} else {
showOldFeature();
}
}
Practices for Operation and Management
Here are three practices to reduce the complexity associated with operation and management when incorporating feature flags into the team's development flow.
Establish a mechanism to remove deprecated feature flags
When feature flags are operated for a certain period of time and their number increases, the code becomes more complex due to increased conditional branching. In order to solve this problem, it is recommended to create a mechanism to remove deprecated feature flags. This involves disabling the target feature flag in the feature flag system and removing the related code.
To ensure that the deprecated feature flags will be removed, adding tasks to the team's backlog or setting deadlines for notifications is effective.
Some teams also incorporate methods such as limiting the number of active feature flags.
Organize feature flags and incorporate them into the development flow
According to an article on martinfowler.com, feature flags can be organized into the following four types, each with different characteristics and usage:
Permissioning Toggles: Used to modify functionality or user experience for specific users only.
Release Toggles: Used to release code that is not yet tested during development as a non-activated feature in the production environment.
Experiment Toggles: Used for conducting A/B tests.
Ops Toggles: Used to control aspects related to the system's operations.
Organizing feature flags and incorporating them into the development flow makes managing feature flags easier.
Test features individually rather than testing all possible combinations of feature flags
When using feature flags, attempting to test all possible combinations of feature flag values during the QA phase can lead to an overwhelming number of test patterns that quickly become unmanageable.
To solve this issue, it is recommended to test features individually rather than test combinations of feature flags. It is important to implement features in a way that they do not affect other features. However, in cases where features are unavoidably dependent on each other, testing combinations of feature flag values that have dependencies can help reduce the increase in test patterns.
Conclusion
In this article, we have explained the best practices for operating feature flags. Since there is no single optimal method for introducing feature flags for all teams, it is necessary to determine the feature flag introduction strategy based on the current requirements and potential future changes.
We hope that the considerations discussed in this article will serve as a reference and you can enjoy the benefits of feature flags while minimizing their drawbacks.