Deployments Not Releases – Get Good at Delivering Software
blog.mangoteque.com
blog.mangoteque.com
If there is any interaction between features you start getting combinatorial explosion of possible code paths, and you all of a sudden get issues that only affect specific customers due to their set of feature flags.
Feature flags have intrinsic complexity. Keeping the code harmonized between customers can cause extra effort when you need to redesign pieces of the system to not need alternative code paths.
Both of these costs should be weighed against each other.
To make matters worse it can be dynamically enabled based on cookies / headers per customer.
For one we have feature flags, which should be used to disable features for certain environments, possibly AB testing and so on. You use those to reduce risk and friction in an ad-hoc fashion. They are meant to be simple booleans in code and short lived.
Then we have feature scope, registration, authorization etc. which can be more wide reaching. They should be part of the data model and treated like everything else that is data driven.
When we conflate the two, we get into trouble like you describe.
Simple? One "simple" boolean often doubles the number of code paths. 10 simple booleans can easily 1024x the number of code paths.
Short lived? There's nothing as permanent as a temporary measure.
Featureflags should never be used for privileged operations assigned to particular users.
Yes in the end it's all in the process, but feature flags are not the end-all be-all these few paragraphs posit them to be.
Another strategy that kind of worked but not as well, is requiring the cleanup of the feature flag to happen in the next sprint. But it tends to be de-prioritized, and sometimes even pushed to the next sprint as other things are always more important.
Another strategy that I've discussed and thought about but never actually implemented or advocated for, is limiting the max amount of active feature flags in the specific project to N numbers (ideally 1). So if you want to activate another feature flag, you have to first cleanup the previous one.
- Ability in code to set the default value in non-production environments such that if a developer never set the flag, it assumes this default value. When a feature is fully released the default should be "on for everyone", generally with the expectation it will be retired soon.
- A required field designating an owner usually a team, but can be a person if your company is small enough
- A field in the flag definition for an expected retirement date
The defaults keep combinatorial explosion down and the other practices make it easy for one responsible person to audit flags and track down responsible parties.
You guys rock. Almost no software companies pay any attention to the fact that every new release imposes a burden on their customers, and rapid release schedules impose that burden rapidly. In a way, it's offloading some of the development burden onto your customers.
This is true for pure SaaS products as well, although to a lesser degree.
I am very happy to hear of a company that remembers this and takes it into consideration.
Downside, of course, is that different customers have different versions of our software on their premises. Support's job is harder, as they need to know "oh, you're on 2.14 and this is a problem with preorders, that bug was fixed in 2.18" for a bunch of historical versions and problems.