Feature flags and authorization abstract the same concept
Monday, April 10, 2023
When I think of feature flags and authorization, I usually think about very different things. They are used for different purposes. But ultimately, they are abstractions of the same thing. They might even be the same thing except for how they are used and the consequences for bypassing them.
But that is a bold claim. Let's establish what we are talking about first.
For this post, feature flags refer to the code and logic that control whether or not a certain feature, page, promotion, etc. are made visible and accessible to a group of users. There are a lot of off-the-shelf solutions for feature flags, such as LaunchDarkly.
These follow a general pattern. They let you use if-else statements in your code to gate features to certain groups of users. At their most basic, they are just on/off switches that you evaluate:
if flags.enabled(MY_FLAG): # do the thing else: # do the other thing
But a full-featured flags implementation will be much more than this. Using it, you typically want to gate features to certain users, roll out features slowly, or even just make it so Sam From Accounting can have the page in dark mode. To do this, many feature flag providers have flags take in a user or context and make the decision based on that.
if flags.enabled(context, MY_FLAG): # do the thing else: # do the other thing
What goes into that context? Whatever you want! And then you can use that context to decide whether or not the user can see something or not.
Phew, okay, that is feature flags. Now, what do we mean by authorization?
Well, first, we do not mean the other auth, authentication. Authentication is roughly making sure that you are who you say you are.
On the other hand, authorization is making sure that users can do what they are supposed to do. They can access their own data, but no one else's without permission. They can see thier own pages, but not someone else's.
Authorization usually works something like this:
if user.has_permission(object.id, ROLE): # do the thing else: # do the other thing
Simply, authorization controls whether a given user can see certain data, pages, etc... wait a second. That sounds familiar.
This is basically exactly what you get from feature flags. Both of these abstract over the same thing, which is just whether or not a given user can do a thing. So if they are so similar, why are they different? Why don't we just have the same implementation for both?
Because they are designed for different uses, ultimately, and the consequences for failure are usually very different. If a feature flag shows someone the wrong promotion, or the wrong theme, or a page they were not supposed to see, it might be embarrassing, but it isn't usually an existential risk. On the other hand, if you show users other people's data, that can cause serious headaches with regulators (looking at you, GDPR).
Another major difference is how long the flags last for. Feature flags are usually ephemeral. There are good reasons to have some permanent feature flags (emergency switches or geographical copy differences, for example). But the vast majority of feature flags are temporary and last until a feature is permanently on or has been abandoned.
In contrast, permissions are forever. Once you have data in your system, you will have to have roles to access that data for as long as you hold it. It is much, much more rare to have a temporary permission for data which you plan to phase out once the feature is complete.
These differences lead to different access patterns, and so feature flag and authorization systems are designed differently to handle these access patterns. Even though they share a commnon underlying concept, feature flags and authorization satisfy very different needs and have different requirements.
But oh how I want to use feature flags for authorization now...