What Are Feature Flags?
Feature flags, also known as feature toggles, are a powerful tool that allows developers to safely deploy and test features in production, while controlling their visibility and impact. They offer benefits such as reducing risks, enabling A/B testing, and supporting a continuous delivery model.
However, while feature flags provide major advantages, they can also introduce complexities if not managed correctly. They can clutter your codebase, lead to technical debt, and even cause unexpected system behaviors if mishandled. We’ll cover important best practices that can help you avoid these pitfalls and make the best use of feature flags in your software projects.
This is part of a series of articles about Feature Flags
In this article:
Main Types of Feature Flags
Before diving into the best practices, let’s cover the main types of feature flags:
- Release flags: These are used to enable or disable features that are in development or being tested. They help in rolling out features incrementally and in managing the release cycle.
- Experiment flags: Also known as A/B testing flags, these are used to conduct experiments by exposing different features or variations to subsets of users. They are instrumental in data-driven decision-making.
- Operational flags: These flags control operational aspects of the system, like feature throttling and infrastructure changes, offering dynamic control without the need for code deployment.
- Permissioning flags: These are employed to manage access to certain features, typically for different user groups or subscription levels. They are crucial in implementing a tiered feature access strategy.
Tips From the Expert
In my experience, here are tips that can help you better manage feature flags in your projects:
-
Set expiration dates for feature flags Assign a lifecycle to each feature flag by setting expiration or review dates. This ensures you periodically evaluate whether flags should be removed, avoiding accumulation of stale flags that contribute to technical debt.
-
Automate feature flag cleanup Use automation to detect and clean up unused feature flags from the codebase. Tools that integrate with your CI/CD pipeline can help flag stale toggles, prompting developers to remove them when they are no longer in use.
-
Monitor feature flag performance impact Feature flags can add overhead to your system, especially when implemented inefficiently. Use performance monitoring tools to measure the impact of flags in high-traffic areas and optimize flag checks for performance-critical sections of your code.
-
Test all flag states in QA Before deploying, test both the enabled and disabled states of each feature flag in your QA environments. This reduces the risk of unexpected behavior in production, ensuring that toggling flags won’t introduce bugs.
-
Create flagging strategies for rollback scenarios Establish clear strategies for feature rollback scenarios. This could include using dark launches, toggling flags off in case of failure, or pre-defining rollback groups. Having a plan minimizes disruptions when rolling back features.
Feature Flag Best Practices
1. Use A Consistent System For Feature Flag Management
Before co-founding Configu, Ran was a full stack developer at Testim.io and previously served in an elite cybersecurity unit in the Israeli Defense Forces.
It’s a good idea to establish a centralized system that allows you to control, track, and manage all your feature flags.
A consistent system provides visibility into your feature flags, helping you avoid flag clutter and mitigate technical debt. It enables you to monitor the status of each flag, understand its impact, and make informed decisions about when to retire a flag. Moreover, a centralized system enables communication across your team, ensuring everyone is on the same page.
Learn more in our detailed guide to feature flag management
2. Set Naming Conventions For Feature Flags
It’s important to categorize your flags based on their purpose, lifespan, or the team responsible for them.
Naming conventions make it easier to identify and manage your feature flags. They reduce ambiguity, prevent naming conflicts, and enhance the readability of your code. Moreover, they enable you to quickly locate a specific flag when needed, especially in a large and complex codebase.
3. Use Abstractions
Abstractions are a key concept in software engineering, and they apply to feature flags as well. When using feature flags, it’s crucial to abstract the flag decision from the application logic.
This practice keeps your code clean and maintainable, and allows you to change the behavior of your feature flags without modifying the application code. This provides flexibility and reduces the chances of introducing bugs.
4. Roll Out New Features Progressively
Rolling out progressively means releasing a new feature gradually, starting with a small audience and expanding over time.
Progressive rollouts reduce the risk associated with deploying new features. They allow you to test the feature in a live environment, gather feedback, and make necessary adjustments before rolling it out to all users. Moreover, in case of an issue, progressive rollouts limit the impact, enabling you to quickly roll back the feature without affecting all users.
5. Cache Feature Flag State Before Entering Loops
When using feature flags in loops, it is crucial to cache the state of the flag outside the loop. This practice helps optimize performance by reducing unnecessary checks for the flag’s state. By caching the flag state, you eliminate the need to repeatedly retrieve the flag value from the configuration or database within the loop.
Caching the feature flag state can be achieved by assigning the flag value to a variable before entering the loop. This way, the flag state is checked only once, and the loop can iterate efficiently without incurring the overhead of repeated flag checks. Remember to update the cached value if the flag state changes during the loop execution to ensure accurate results.
6. Avoid Dependencies Between Flags
To ensure flexibility and independence, it is crucial to avoid creating dependencies between feature flags. Dependencies can arise when the behavior of one feature flag relies on the state of another flag. This can lead to unintended consequences and make it harder to manage and test the system.
Instead, strive for feature flags that can be toggled independently without affecting the behavior of other flags. If there is a need for interdependence, consider using feature flag groups or conditionals that encapsulate the logic. This approach allows for more controlled and predictable interactions between flags and avoids unnecessary complications.
7. Don’t Nest Feature Flags
While it may be tempting to nest feature flags within each other to create complex combinations of features, it is generally best to avoid this practice. Nesting feature flags can quickly lead to code complexity and reduce maintainability. Instead, aim for a flat structure with individual feature flags that can be toggled independently.
By keeping feature flags separate, you simplify the code logic and make it easier to reason about the behavior of each flag. Additionally, a flat feature flag structure allows for clearer communication among team members, as they can easily understand and discuss the impact of each flag on the system.
8. Use Feature Switch To Avoid Code Branches
One of the main benefits of feature flags is the ability to control the release of new features without creating multiple code branches. However, if not properly implemented, feature flags can introduce branching logic that can be hard to maintain and understand.
To avoid excessive code branching, consider using feature switches. A feature switch is a centralized mechanism that encapsulates the logic for enabling or disabling a feature. By using a feature switch, you can keep the codebase clean and avoid cluttering it with conditional statements based on feature flag states.
A feature switch can be implemented as a separate class or module that handles the enabling and disabling of a specific feature. This approach centralizes the decision-making process and makes it easier to manage the state of the feature across the codebase.
Feature Flags with Configu
Configu is a configuration management platform comprised of two main components:
Configu Orchestrator
As applications become more dynamic and distributed in microservices architectures, configurations are getting more fragmented. They are saved as raw text that is spread across multiple stores, databases, files, git repositories, and third-party tools (a typical company will have five to ten different stores). Configu can work as a stand-alone platform or as an orchestrator for secrets managers, feature flags and other stores. It has built-in support for popular feature flag managers, such as Launch Darkly.
The Configu Orchestrator, which is open-source software, is a powerful standalone tool designed to address this challenge by providing configuration orchestration along with Configuration-as-Code (CaC) approach.
Configu Cloud
Configu Cloud is the most innovative store purpose-built for configurations, including environment variables, secrets, and feature flags. It is built based on the Configu configuration-as-code (CaC) approach and can model configurations and wrap them with unique layers, providing collaboration capabilities, visibility into configuration workflows, and security and compliance standardization.
Unlike legacy tools, which treat configurations as unstructured data or key-value pairs, Configu is leading the way with a Configuration-as-Code approach. By modeling configurations, they are treated as first-class citizens in the developers’ code. This makes our solution more robust and reliable and also enables Configu to provide more capabilities, such as visualization, a testing framework, and security abilities.