Feature Flags are configurations that specify whether product features are active or inactive.
Features flags is an essential mechanism for enabling software teams to move fast: they allow teams to decouple from each other and deploy software independently, they also allow teams to decouple software delivery from market-facing software releases – sometimes those are timed to marketing campaigns, industry events, or customer schedule.
Static vs. Dynamic
Feature flags can be static or dynamic. Static feature flags simply specify whether a feature is active or inactive. Dynamic feature flags make that determination during runtime based on specified configuration – IP address, account ID, username, day of the week, phase of the moon, etc. My preferred name for the latter type is Flexible Feature Flags.
Flexible feature flags give teams more flexibility and are generally not that much harder to implement – but they require some upfront thinking from teams.
Best practices for working with feature flags:
- Imagine a very typical situation – a production issue that can be addressed by turning a feature off. The mechanism must allow for changes to feature flags to take effect quickly – no more than a couple of minutes, ideally seconds. It is highly undesirable to need to redeploy software for feature flags to take effect.
- Unreviewed changes to feature flags made directly in production are very dangerous. The source of truth for feature flags must be in version control. This makes changes to feature flags traceable and allows teams to code review them before they take effect.
- An automated solution should be used to deploy feature flags from version control to production. This makes the process deterministic and also allows teams to run new configurations through automatic testing and validations before deploying them. This also make it easy to trace which settings are in effect in which environment
There are typically two types of mechanisms used for implementation of feature flags:
- Configurations are deployed to one central location (DB, Config Server, etc.), which gets polled by individual software components
- Configurations are distributed to individual hosts and take effect without restarting software
Most solutions that I have seen are variations on the former.
Working with Legacy
In my experience, most teams already have a mechanism in place that allows them to distribute configurations to components quickly. They can implement a feature flags solution by piggybacking on that existing mechanism.
If such mechanism don’t exist, I still encourage teams to utilizing existing infrastructure as much as possible. This allows teams to create a working prototype within days, without making big investments up front.
For static flags a simple key-value format does the job. For Flexible feature flags I encourage teams to keep syntax light and flexible. Teams often choose JSON or YAML.
The inevitable question from developers is “how do we prevent code from turning into spaghetti, littered with a bunch of if statements?”
- The smart sounding answer is “use Factory and Strategy patterns to avoid if statements.”
- In practice, I have never seen this utilized. Most teams use simple if statements and then make sure to remove them after the feature becomes permanently active. This happens organically and doesn’t require a dedicated clean-up effort. Teams should be encouraged to pay attention to this during code reviews.
I have seen teams overdo it—come up with a very complex hierarchical solutions for configurations that allow for inheritance of settings, overrides per environment, etc. Such solutions are overkill for this problem. If the source of truth is in version control and an automated process is used to propagate changes to production, there is no need for additional complexity.