Release Delayed for a Single Feature? Feature Flags to the Rescue!

Charaka Gunatillake
Insights by Insighture
11 min readMay 22, 2024
Photo by Karim MANJRA on Unsplash

Ever had to hold off a release because your Product Manager had not given the go-ahead for a single feature yet?

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.

The Problem

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?

Photo by Jan Huber on Unsplash

A Solution: Feature Flags

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.

Controlled Feature Release

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.

Immediate Response to Bugs

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.

Iterative Testing and Rollout

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.

Other Advantages

In addition to its main advantages, there are many other less-discussed advantages of feature flags. Some of them are as follows:

  • Easier to do gradual rollouts — For example, you can release the feature to the users in Region A first, then Region B, Region C, and so on, before releasing it to all the users.
  • Support for A/B testing — If you need to do A/B testing to figure out how the users would react to the product with the feature and without it, you can simply turn on the feature for a subset of users using feature flags.
  • Improved team collaboration — Feature flags enable developers to work concurrently on new features without affecting each other’s code or disrupting the primary codebase.
  • Emergency switch — In case you have to disable a particular feature due to an unexpected reason, the feature flag can act as an emergency switch. This doesn’t have to be a bug; it could be due to a sudden compliance requirement or a change in the product strategy.

How to Implement Feature Flags

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:

  1. If you are at the very early stage of your product, you can simply use environment variables. This will not give you much control as to which users or regions may access a given feature, however, it will provide a very simple way to enable/disable features without introducing too much complexity into the code.
  2. As time goes on, you can consider maintaining feature flag configurations in a database along with the user groups that have access to a given feature. This will provide more control allowing feature flags to be enabled for different user groups.
  3. Eventually, it might make sense to inject feature flags into the relevant context with the use of middleware, as you need to use the same feature flags over multiple places.
  4. As your system grows and needs better control over the features, you can consider either maintaining a separate configuration service that also handles feature flags or even use 3rd party services such as AWS AppConfig and GitLab feature flags to maintain feature flags.
  5. At this point, things are gradually becoming complicated. You need to think carefully about the trade-offs to ensure that you still gain good value out of feature flags. If you use such 3rd party services, there are other factors to consider such as cost impact (which is beyond the scope of this article). Also, you would have to think about the additional complexity introduced by the feature flags and how to mitigate them.

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.

Choosing Libraries/Frameworks

When implementing feature flags, several out-of-the-box solutions can help you. Some of those are as follows:

  • Standalone Libraries such as Togglz and FF4J (for Java), FeatureToggle (for .NET), fflip (for Node.js), and Flipper (for Python).
  • OpenFeature, an open standard for feature flag management, provides a consistent API across different providers which also offer SDK implementations compatible with their standard for popular languages.
  • Open-source platforms such as Unleash, PostHog, and Flagsmith provide feature flagging solutions that can be hosted on-premise or used with their cloud offerings, giving you the choice of where to manage your feature flags.
  • GitLab Feature Flags, a built-in feature flag management within GitLab’s DevOps platform.
  • AWS AppConfig, a part of AWS Systems Manager that enables safe deployment of application configurations, including feature flags, without requiring a full deployment.

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.

The Drawbacks of Feature Flags

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:

1. Testing with feature flags for multiple related features can be problematic

  • 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.

2. Accumulation of a lot of feature flags over time increases technical debt

  • 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.

3. Performance overhead

  • 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

3. Potential misuse

  • 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.

When It Is Not Recommended to Use Feature Flags

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.

Photo by Markus Spiske on Unsplash

1. Core system changes

  • 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.

2. Security and performance-critical changes

  • 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.

3. Long-term feature management

  • 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.

Conclusion

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!

Written for Insighture Technology.

--

--