So I have a year of professional development experience. I have worked only with feature branches so far, but have heard about the feature flags way of doing things.
What I don’t get is:
What if one commit introduces new behavior that has a bug, and another commit references the buggy piece of code from the previous commit.
As I understand it, every commit has its own feature flag?
So when the bug is realized, you turn off both of the feature flags introduced in these two commits?
Im just wondering about the domino effect - what if one flag needs to be turned off, and that code path influences other paths?
First off, yes... Feature Flags do add some complexity, and absolutely require more attention and forethought. You can screw it up, so a bit of extra care is required moving forward.
But the payoff is grand. When done well, you get a ton of benefits (like being able to deploy more often, turn features off if they don't work, and avoid re-deployment nightmares). But all those benefits aren't necessarily "free" (or maybe I should say "a breeze") to implement.
Does every commit have its own feature flag?
No. Not necessarily. And, more context, please. 😉 I'm not sure if you literally mean "every commit," or how often you are committing. My preferred workflow is to commit very, very frequently (potentially dozens, maybe even a hundred times in a day). That could be to my local or to a branch, doesn't really matter – but in that mode working, no each commit will not have its own flag. In my preferred approach, each *merge* (or, more accurately, each *PR*) will have a flag. The PR itself... might consist of many, many small commits that I made during the day.
What if two (new) flags depends on each other?
So, with that context out of the way – what if we have two different flags that depend on each other? And does it matter if they are both new or if one has been there for a while?
There are probably a few ways to figure this out – but my solution is that you have to build that dependency into your code. If there's an existing flag 'F-1' and I come along and build a new feature, and it requires 'F-1' to be active... then my PR is going to have to reflect that. My PR needs to make sure my new flag can only be turned on if 'F-1' is also turned on. Likewise, I probably need to commit a bit of code so that if 'F-1' is turned *off*, then my flag is automatically turned off too.
> What if one commit introduces new behavior that has a bug, and another commit references the buggy piece of code from the previous commit?
So... yes, there's is the potential for flags to influence each other, and sometimes it can get a little bit tricky. Try not to simultaneously deploy a lot of co-dependent flags. Doing them in sequence simplifies root cause analysis.
Sometimes you'll have codependent flags that don't have the dependency logic built in. That happens. E.g., "Oh my, we noticed a bug in F-1 and that seems to be causing F-7 to break too! What do we do?" Well, you turn them both off. Then you capture the bug, and part of the fix should be "implement automatically disabling F-7 if F-1 is turned off," just to keep things neat.
Cleaning up.
The other things to keep in mind – flags don't stick around. They should be transitory. This requires forethought.
You want to clearly demarcate your old code, the stuff that is not being called when a flag is enabled. Then, once you're sure all is well, you go back and remove the old code, and remove the flag. You don't want tons of feature flags living forever in your code (along with stale, unused code that will never be called).
For me, it's a bit of a code smell if there are more than handful of feature flags alive at any time. "A handful" varies by project... for my personal projects, a couple is probably my tolerance. For a big, 40-person project, maybe a dozen or so... context matters. Mostly, I just want to make sure that when I look back at the code base, things that have stabilized should no longer have flags attached to them.
Hope that helps! It does take more effort, for sure – but, it's a little bit more effort up-front in the planning and development, and you recoup it in the long run with all the benefits. But the planning bit is super-important!
Sorry for not being precise - yes, when I said commit I actually meant PR - my bad.
Your answers have provided a lot of insight to me. I like the benefit that you emphasized - being able to shut down a feature - yeah, that sounds great, we dont have to wait to solve a bug that appeared, we can just turn off the entire feature until we solve the bug and rollout a patch.
I also thought that all of the features should have flags, but your answer covered this incorrect assumption as well. It is actually only the “newer” features that have flags, and with time they will become stable old features and not need flags anymore.
Thanks for taking the time to write such a long detailed answer, im really glad I asked the questions!
So I have a year of professional development experience. I have worked only with feature branches so far, but have heard about the feature flags way of doing things.
What I don’t get is:
What if one commit introduces new behavior that has a bug, and another commit references the buggy piece of code from the previous commit.
As I understand it, every commit has its own feature flag?
So when the bug is realized, you turn off both of the feature flags introduced in these two commits?
Im just wondering about the domino effect - what if one flag needs to be turned off, and that code path influences other paths?
Those are great questions, Stefan.
First off, yes... Feature Flags do add some complexity, and absolutely require more attention and forethought. You can screw it up, so a bit of extra care is required moving forward.
But the payoff is grand. When done well, you get a ton of benefits (like being able to deploy more often, turn features off if they don't work, and avoid re-deployment nightmares). But all those benefits aren't necessarily "free" (or maybe I should say "a breeze") to implement.
Does every commit have its own feature flag?
No. Not necessarily. And, more context, please. 😉 I'm not sure if you literally mean "every commit," or how often you are committing. My preferred workflow is to commit very, very frequently (potentially dozens, maybe even a hundred times in a day). That could be to my local or to a branch, doesn't really matter – but in that mode working, no each commit will not have its own flag. In my preferred approach, each *merge* (or, more accurately, each *PR*) will have a flag. The PR itself... might consist of many, many small commits that I made during the day.
What if two (new) flags depends on each other?
So, with that context out of the way – what if we have two different flags that depend on each other? And does it matter if they are both new or if one has been there for a while?
There are probably a few ways to figure this out – but my solution is that you have to build that dependency into your code. If there's an existing flag 'F-1' and I come along and build a new feature, and it requires 'F-1' to be active... then my PR is going to have to reflect that. My PR needs to make sure my new flag can only be turned on if 'F-1' is also turned on. Likewise, I probably need to commit a bit of code so that if 'F-1' is turned *off*, then my flag is automatically turned off too.
> What if one commit introduces new behavior that has a bug, and another commit references the buggy piece of code from the previous commit?
So... yes, there's is the potential for flags to influence each other, and sometimes it can get a little bit tricky. Try not to simultaneously deploy a lot of co-dependent flags. Doing them in sequence simplifies root cause analysis.
Sometimes you'll have codependent flags that don't have the dependency logic built in. That happens. E.g., "Oh my, we noticed a bug in F-1 and that seems to be causing F-7 to break too! What do we do?" Well, you turn them both off. Then you capture the bug, and part of the fix should be "implement automatically disabling F-7 if F-1 is turned off," just to keep things neat.
Cleaning up.
The other things to keep in mind – flags don't stick around. They should be transitory. This requires forethought.
You want to clearly demarcate your old code, the stuff that is not being called when a flag is enabled. Then, once you're sure all is well, you go back and remove the old code, and remove the flag. You don't want tons of feature flags living forever in your code (along with stale, unused code that will never be called).
For me, it's a bit of a code smell if there are more than handful of feature flags alive at any time. "A handful" varies by project... for my personal projects, a couple is probably my tolerance. For a big, 40-person project, maybe a dozen or so... context matters. Mostly, I just want to make sure that when I look back at the code base, things that have stabilized should no longer have flags attached to them.
Hope that helps! It does take more effort, for sure – but, it's a little bit more effort up-front in the planning and development, and you recoup it in the long run with all the benefits. But the planning bit is super-important!
Sorry for not being precise - yes, when I said commit I actually meant PR - my bad.
Your answers have provided a lot of insight to me. I like the benefit that you emphasized - being able to shut down a feature - yeah, that sounds great, we dont have to wait to solve a bug that appeared, we can just turn off the entire feature until we solve the bug and rollout a patch.
I also thought that all of the features should have flags, but your answer covered this incorrect assumption as well. It is actually only the “newer” features that have flags, and with time they will become stable old features and not need flags anymore.
Thanks for taking the time to write such a long detailed answer, im really glad I asked the questions!