Better Defect Reduction: AI Applications in Your Quality Engineering Maturity Journey
The next time you sit down with your Chief Innovation Officer, bring up quality maturity as an agenda item. Artificial intelligence (AI) exists with …
READ MOREEver had to hold off a release because your PM had not yet approved that single feature?
Wish you could test-drive new software features before fully committing them to every user out there?
What if you could switch a new feature on or off instantly - without redeploying your entire application?
Meet feature flags (AKA feature toggles), a software development technique to confront these very challenges.
In this article, we are going to discuss the problem that feature flags are trying to solve, how feature flags solve them, their main advantages as well as some of their less discussed advantages, ways to implement feature flags in an evolutionary manner, the problems that can arise with the use of feature flags, how to mitigate them and finally when it is NOT recommended to use feature flags at all.
In software development today, it is crucial to deploy features quickly that respond to user needs and market conditions. Innovation is expected to rapidly enhance user experience, streamline processes, and consider sustainable practices if it is to make an impact.
Traditional software deployment strategies often involve rolling out large updates at infrequent intervals. This approach poses several challenges.
First, it increases the risk of introducing bugs that can affect all users simultaneously, leading to widespread disruptions. Secondly, it makes it difficult to test new features in real-world conditions without impacting all users. Finally, it makes it difficult to quickly adjust or roll back features based on user feedback or performance issues.
Imagine you have a deployment to introduce a major new feature in photo-editing software that you develop. Traditionally, this feature would be bundled with other updates in a large quarterly release. However, just hours after the rollout, reports flood in about a critical bug that causes the software to crash during the saving process - a bug missed during testing because it only occurs under specific conditions that were not replicated in your test environments.
With the entire user base already updated, the bug impacts a significant number of users simultaneously, causing frustration and disrupting their work. The team scrambles to identify and fix the issue, but in the meantime, users are left dealing with the fallout. The pressure mounts to roll back the update, but it is a cumbersome process due to the interdependencies with other features and fixes included in the same release.
Then, as a result, development teams may find themselves grappling with the question: To deploy or not to deploy?
Is there a way out of this dilemma?
Feature flags are simple in concept: they allow developers to enable or disable features remotely without deploying new code. This is done by wrapping the feature in a conditional statement that checks if the flag for that feature is turned on or off.
Example Code Block 1: Very simple feature flag mechanism
// Assume we have a configuration object that might come from an API or environment variable
const config = {
features: {
newDashboard: true // The feature flag for the new dashboard feature
}
};
// Function to check if a feature is enabled
function isFeatureEnabled(featureName) {
return config.features[featureName];
}
// Usage of the feature flag
if (isFeatureEnabled('newDashboard')) {
console.log('New Dashboard feature is enabled.');
// Code to render the new dashboard
renderNewDashboard();
} else {
console.log('New Dashboard feature is disabled.');
// Code to render the old dashboard
renderOldDashboard();
}
They provide an innovative solution to the challenges highlighted in the scenario with the photo-editing software mentioned earlier. By integrating feature flags into the deployment process, software teams can mitigate the risks associated with large, infrequent updates and respond more agile to unforeseen issues.
Using feature flags, the new major feature in the mentioned photo-editing software could have been wrapped in a toggle, allowing it to be deployed by default. This approach permits the team to activate the feature selectively, perhaps starting with a small group of users or even internal testers. This controlled environment would enable real-world testing without exposing the entire user base to potential risks.
Once the critical bug was identified in the software’s saving process, the developers could immediately disable the feature for all users with a simple change in the feature flag’s status. This quick response prevents widespread disruption and maintains user trust, as the majority of users would not encounter the bug before it was addressed.
With the feature flag approach, after the initial discovery and mitigation of the bug, developers can work on a fix in a lower-pressure environment. Once resolved, the feature can be incrementally re-enabled for subsets of users to ensure the issue is genuinely fixed. This iterative process allows for safer deployment and a better understanding of the feature’s behavior in diverse real-world conditions.
In addition to its main advantages, there are many other less-discussed advantages of feature flags. Some of them are as follows:
There are multiple ways to implement feature flags. The feature flags can be implemented as a part of your system itself or you can use 3rd party services. It’s important to understand that feature flags add a bit of technical complexity. However, it can vastly reduce the complexity of the delivery flow, when there are a lot of people working on the same codebase on different features. Considering that, we need to use feature flags in such a way that it can reduce the overall complexity when we think of everything as a whole. Perhaps, the ideal way to implement depends on your requirements, and your approach can evolve as your requirements evolve.
For example:
Note that here we only aim to illustrate a general idea of how feature flags may be implemented in an evolutionary manner, not to recommend the most suitable approach for your specific requirements.
When implementing feature flags, several out-of-the-box solutions can help you. Some of those are as follows:
While these are some of the popular libraries, frameworks, and services at the time of writing, it is important to evaluate whether they are still actively maintained, check for any security vulnerabilities, and, if considering a cloud offering, review their pricing and support options before choosing one for your project.
Feature flags indeed have a lot of advantages. However, as mentioned before feature flags also introduce some level of complexity into the code. That means there are some drawbacks as well. If not used appropriately, the feature flags can complicate your codebase as well as your deployment processes.
Example Code Block 2: Code with Feature Flags Overlapping
// Assume we have a configuration object that might come from an API or environment variable
const config = {
features: {
featureA: true, // First feature flag
featureB: false // Second feature flag
}
};
// Function to check if a feature is enabled
function isFeatureEnabled(featureName) {
return config.features[featureName];
}
// Function to decide the behavior based on multiple flags
function determineFeatureBehavior() {
const featureAEnabled = isFeatureEnabled('featureA');
const featureBEnabled = isFeatureEnabled('featureB');
if (featureAEnabled && featureBEnabled) {
console.log('Both Feature A and Feature B are enabled.');
executeCombinedBehavior();
} else if (featureAEnabled) {
console.log('Only Feature A is enabled.');
executeFeatureAOnlyBehavior();
} else if (featureBEnabled) {
console.log('Only Feature B is enabled.');
executeFeatureBOnlyBehavior();
} else {
console.log('Both Feature A and Feature B are disabled.');
executeDefaultBehavior();
}
}
// Execute the feature behavior based on current feature flag configuration
determineFeatureBehavior();
Some of the drawbacks and ways to mitigate them are as follows:
Let’s say there are 2 related features and each of those has a specific feature flag. Now since those features are related, the product may function in 4 different ways (2x2) depending on which feature is turned on and which feature is turned off. If there are 3 or even more feature flags that overlap on the boundaries of each other, the codebase can increase in complexity exponentially and make the code less readable as well as a nightmare to test.
How to mitigate this:
It is important to add feature flags in such a way that it would minimise the chance that the relevant block of code would overlap with the boundaries of another feature flag.
If we have to add, grouping the logic centrally to ensure combinations are checked in one place may keep the code more readable.
As a product grows, it can result in 100s of feature flags that have been added at different points in time. Even removing many feature flags at once might introduce new bugs and might require more testing.
How to mitigate this:
Removing any feature flag immediately after it is no longer needed (for example, at the point the feature had been tested on the production and the stakeholders agree that it is going to be a permanent feature of the codebase).
As a part of your software development process, you can define the point at which a feature flag needs to be removed.
Feature flags can introduce performance overhead. Each check of a feature flag is a decision point that could potentially slow down the application, especially if the flags are checked frequently within performance-critical parts of the application.
How to mitigate this:
In the parts of the code where the performance is critical, the development team can make a conscious effort to reduce the use of feature flags and also not to keep them more than they are needed.
Another solution is to make performance improvements on how the application retrieves feature flags
Feature flags can be misused as a means to bypass proper testing or to rush unready features into production. This misuse can lead to stability issues and degrade the overall quality of the application.
How to migrate this:
Having proper protocols in your development process to ensure that feature flags are used only for their intended purpose can mitigate this.
More importantly, making sure that the team understands the why behind having feature flags and the vices as well as virtues of using feature flags will prevent potential misuse.
Yes, you read that correctly! Feature flags are not the answer to everything. There are times when we should avoid the use of feature flags altogether and seek alternative solutions.
For changes that impact the foundational architecture of a system - such as database schema updates, changes to critical infrastructure components, or major revisions that affect the overall system architecture - feature flags may not be the right tool. These changes often require careful planning, comprehensive testing, and sometimes a complete system migration which feature flags cannot facilitate adequately. In rare cases, you might consider temporarily testing certain architectural changes under a feature flag as you do exploratory work. However, feature core systems changes are not meant to be kept under feature flags.
Earlier we mentioned that feature flags may introduce performance overhead and ways to mitigate them. However, if the changes are very critical be it security-related changes or performance-critical changes, it is better not to use feature flags at all.
While feature flags may be useful for releasing features in a controlled manner, it is not intended to be used for long-term feature management. Feature flags that are left active in the code for an extended period can lead to technical debt. If there is a need to keep features configurable in the long term, it is better to use a separate configuration management mechanism.
In conclusion, feature flags offer a good solution to the problem of safely introducing and testing new features in a live environment without disrupting the overall user experience. At the same time, we need to be careful to manage and retire these flags appropriately to avoid increasing technical debt and complexity in the codebase. Furthermore, we need understanding and good judgment to mitigate the downside of feature flags and to determine when it is not appropriate to use feature flags.
Finally, we also need discipline and a bit of courage not to misuse feature flags as a means to rush unready features into production!
The next time you sit down with your Chief Innovation Officer, bring up quality maturity as an agenda item. Artificial intelligence (AI) exists with …
READ MOREAI has been an anticipated technological breakthrough, taking over most manual white-collar jobs today. PwC’s Global AI Study reveals that AI will …
READ MORE