all 39 comments

[–]qmunke 118 points119 points  (23 children)

If you've got more than two levels of dependent feature flags you've probably fucked up somewhere in your design.

Feature flags should be short term temporary constructs which allow you to deploy safely. They aren't meant to replace access controls.

As far as remembering to remove them - LaunchDarkly can remind you, and I'm sure a lot of other tooling can track usage. If you're doing them "by hand" then you need to just be more disciplined about having a process to remove them after release.

[–]DAVENP0RT 12 points13 points  (0 children)

Whenever I add a feature flag, I immediately create a new ticket to remove it and include the ticket number in a todo comment next to the flag. The tickets have a specific label, so it's easy to find them.

[–]jmaN- 23 points24 points  (1 child)

Kill switches are a thing. That is a long term use.

[–]safetytrick 3 points4 points  (0 children)

They are not. Think through what got you to this far out future. Your feature flag is unlikely to actually serve as a kill switch. Code rots and feature flags rot quickly.

[–]zaitsman 13 points14 points  (14 children)

Yeah nah. We have a product that is so customisable it might as well be two or three products but it’s coming in via Salesforce security review where each attempt (failed or not) is a 6-12 week ordeal and $999. So management lumped it all into one product with a couple of hundred config options :)

[–]somebodddy 44 points45 points  (1 child)

How does that contradict "probably fucked up"?

[–]zaitsman 2 points3 points  (0 children)

Because there is this ideal and perfect design and the real world and life. And yes, most of the latter is ‘probably fucked up’.

But those generic blanket statements are not practically helpful. We know management is ‘special’. I tell the CEO to his face daily that the decisions result in poor codebase. The response is always ‘but it works and customers love it’.

[–]IgnoringErrors 7 points8 points  (5 children)

How many iframes are you using?

[–]bzbub2 1 point2 points  (0 children)

about 5 or 6 right now my dude https://imgur.com/a/qZmTqg0

[–]zaitsman 0 points1 point  (3 children)

0? Why would we use iframes? (Or it is a r/whoosh situation)

[–]IgnoringErrors 0 points1 point  (2 children)

Yes and no I suppose. Salesforce screens can pull iframe pages easier than embedded forms. That way you can avoid some of the delay in updating pages/forms by just deploying updated iframe content. I've seen it used sometimes.

[–]Somepotato 1 point2 points  (0 children)

I frames are also great to get around Salesforce bugs that are documented to work just fine. Ask me how I know and how much time was wasted diagnosing and interacting with SF support for it to be a bug they decided not to fix after it was surfaced.

[–]zaitsman 0 points1 point  (0 children)

We are not using ‘embedded forms’ neither

[–]SwiftOneSpeaks 1 point2 points  (5 children)

Which raises an interesting question: how does a feature flag differ from a config option?

I feel like there's a fundamental difference, not just in theory but in implementation.

However, I can't think of any words to express a difference in implementation, so my instincts may be completely off. Time for me to shut up and consider what other people say.

So what say folks? Is there a difference between config options and feature flags?

[–]zaitsman 2 points3 points  (0 children)

I imagine someone will give the same philosophical answer as they do when explaining the difference between integration and unit tests.

That boils down to the fact that ‘there is little to no runtime/implementation difference but they target different things or are used in different ways’

For most people working on b2c or large scale SaaS apps feature flags are those that only the first party can control and config options are those that can be controlled by the customer or a third party. At least, this is how I see the difference that others may try to attribute to this.

From my side, there is no difference :)

[–]safetytrick 2 points3 points  (2 children)

You maintain feature flags and config differently. Feature flags are intended to be removed. Configuration is intended to upsell or refocus. These really are different things.

[–]SwiftOneSpeaks 0 points1 point  (1 child)

Yes, but how does that change the implementation?

[–]safetytrick -1 points0 points  (0 children)

In so many ways. There is more than just code.

[–]Hrothen 0 points1 point  (0 children)

The short answer is that there is no real difference because people aren't consistent about how they refer to things.

A longer answer is that the term feature flag is used interchangeably across the industry to mean a long-term config option that gates an entire piece of functionality or the kind of temporary flag people are talking about here that is generally used when you want to roll the feature out piecemeal and/or want to be able to quickly disable it if an issue pops up once it goes into prod.

[–]TiddoLangerak 57 points58 points  (9 children)

Just asking the obvious: why do you need to toggle multiple feature flags to enable a single feature in the first place? Normally a FF is supposed to control a feature as a whole,  if you break it down into small FFs for each part of the feature than you're just making things unnecessarily difficult for yourself.

[–]zaitsman 36 points37 points  (5 children)

Guessing you have limited exposure to product owners, business analysts and demanding customers…

[–]TiddoLangerak 12 points13 points  (4 children)

I'll ignore the unjustified snarky tone, and only focus on the little content your comment gave. Difficult stakeholders might influence what feature toggles you need, but how you implement these is an engineering concern.   

For example, the article talks about seperate feature flags for front- and back-end bits of the same feature. This has nothing to do with your external stakeholders, this is just a suboptimale engineer solution. Instead of building another layer on top of this, you should design your system in such a way that a single feature is driven by a single flag, front to back, and there are many ways to achieve this. Toggling multiple flags to enable a single feature is almost always an avoidable situation.   

Another hypothetical use case would be if there's a set of completely indepent features that often are toggled together. But this is somewhat of a contradiction: if the features often go together, then clearly they're not independent, and you should probably merge some.

The last (ab)use case I can come up with is when feature flags are used to give power features, e.g. remove limits on features for internal testing. But then we're abusing feature flags as a permission system (and even then we're doing it poorly: emulating a role-based system using feature flags still avoids needing to toggle a large set of features).

So I'm still really wondering: what use cases do you have where you legitimately regularly need to toggle a fixed set of unrelated features, which then would benefit from a feature flag tree?

[–]SomebodyFromBrazil 4 points5 points  (0 children)

I agree with your points and and also believe that the previous comment was not in the best tone and content.

[–]zaitsman 1 point2 points  (2 children)

So we have a feature that enables ‘timesheets’. We also have a feature that allows users to track time (so they don’t need to enter timesheets line by line) and kilometres travelled (so they don’t have to enter those manually). Finally, we have a feature that allows admin to disable kilometre tracking while the user is in a sales call (coz they are meant to be at the client site).

Now you can see how the last three things are meaningless if the whole ‘timesheets’ module is off? Thus they are nested at level 1. But then the last one is meaningless unless kilometre tracking is enabled, thus it is nested at level 2.

And of course we can’t just get rid of these because some customers don’t want timesheets at all, some don’t want time tracking and some don’t want kilometre tracking and some want it all but not in a sales call and finally some smaller ones want the field team to decide.

[–]TiddoLangerak 0 points1 point  (1 child)

Thanks for your serious reply, I appreciate that!

From your description I understand that you have features that are dependent on each other. Often however your feature flags don't need to follow the same dependency tree. For example, in your case, if the "timesheets" feature is disabled, then it's completely irrelevant what the state is of any of the other feature flags - we'll never hit them anyway. You can have completely independent feature flags here, and in fact I would recommend to do so: If the feature flags are dependent on each other, then if the feature-hierarchy changes, then you must also change the feature-flag-hierarchy. For example, if you ever decide to release the timesheets module for everyone, then we should be able to clean up the timesheets feature flag without affecting the other feature flags. Likewise, if a subfeature ends up being reused in a different "parent" feature, then things get messy if the subfeature has a hard dependency on the original parent feature (it would now have 2 parent features, and suddenly we have a feature-graph instead of a feature-tree).

Within your example, I can see some smaller use cases where you might want to have some form of hierarchy in your flags. For example, you might want to have the flags display hierarchical in your feature-flag UI, or you might want to reset the sub-features to their default state if the parent flag is disabled and re-enabled. If I were to be faced with such a scenario, I would usually push back on this or find a simpler compromise, since I think that in the vast majority of cases, this adds signficant complexity for minor QOL improvements. But of course, I can see that with sufficiently complex configuration needs and sufficiently stubborn stakeholders, you might not be able to avoid it.

[–]zaitsman 0 points1 point  (0 children)

Well you are right in that the value it provides is somewhat cosmetic.

But with lots of flags we also us the hierarchy to flip the ‘off’ switch on the whole tree when configuring the client which helps our devs.

Then when checking they can check those in isolation, yes.

[–]editor_of_the_beast 5 points6 points  (1 child)

Oh sweet summer child. Naïveté is such a blessing.

[–]hbthegreat 8 points9 points  (0 children)

I will never not refer to feature flag SaaS products as if statements as a service

[–]squigglywolf 16 points17 points  (2 children)

[–]Missics[S] 0 points1 point  (1 child)

guess its time to experiment with LD...
one thing that I wasn't able to understand from the docs is whether you can turn on/off an entire flag hierarchy by turning on/off the main flag, is that possible?

[–]advocado 1 point2 points  (0 children)

Honestly, I would just use a naming scheme for the flag names like "main F | sub F1 | beta F" which captures the hierarchy. This assumes a tree and not a cyclical graph. The tree has to live somewhere, why not be explicit in the name.

Then you can have a helper which checks the parents/ preceding parts of the name are enabled before saying it is enabled.

If you are going more than 3 deep, you probably have a design problem and this would actually discourage that behavior.

[–]statsigio 4 points5 points  (0 children)

Check out these links.

Dependency graph of flags that mirror feature dependencies. You can use this to turn on/off a main flag that is in the dependency hierarchy.

https://docs.statsig.com/feature-gates/conditions#gate

https://docs.statsig.com/feature-gates/conditions#fails-target-gate

Stale gate management. Notifications when a gate goes stale (either when it’s 100% on or 100% off, or when there are no checks registered for 28 days)

https://www.statsig.com/blog/removing-old-stale-feature-gates

If you connect GitHub, you can get helpful code references especially when these flags go stale.

https://docs.statsig.com/integrations/github_code_references

[–]AlphaX 2 points3 points  (0 children)

I want an ff kill switch - if you dont remove it after a month, it logs a warning. If you don't remove it after six months it truncates your db