Just because they have the same implementation doesn't mean they're the same concept.
The concept behind feature flags is, "this person will have access to this feature some day, and I (am / am not) ready for them to see it yet." They're shortlived, tend to be sprinkled throughout the codebase, and need to be aggressively removed to prevent a mess. The consequences for failure are usually minor.
The concept behind authorization is, "this person (does / does not) have this capability, and they absolutely must not be given capabilities they don't have." They're long lived, have extraordinary consequences for failure, and need careful design to make sure they're centralized and easy to reason about.
These are vastly different needs that demand different design approaches.
There's a lot of gray area, though. Consider the statement: "This person (does/does not) have the ability to see Widget X on their homepage."
From the perspective of someone implementing the frontend or backend? It has all the characteristics of a feature flag.
But what if Widget X shows something we are not allowed to sell to that person (say, per a specialized contract with their organization, or regional/legal limitations)? Then it's long lived, has extraordinary consequences for failure, and needs careful design to be able to model the person's membership in different (often overlapping) labels or organizations.
We implement a `resolve_config` function used across our codebase, where different entities in our data model have a well-defined precedence order when they can override the value iff they match part of the hierarchical context. It's designed to be a near-zero-cost abstraction (cached locally so lookups can be done synchronously). That way, doing something that will roll out to some partners over time, and never to other partners, is as simple as using this function instead of a constant or literal. Edits at any level are audit-logged and can, when necessary, have approval procedures applied. It's an authorization system, at its core, but with arbitrarily typed values rather than boolean authorized-or-not flags. And I can't imagine building a B2B or B2B2C business without it.
What if features are permanent, eg users in Brazil get to see certain products, a special import-tax panel, etc, but no-one else does? What if authorized users leave?
The concepts are similar if not the same if you ask me (access control), just as the article points out, but they generally have different uses and patterns of use, again, just as the article points out.
> users in Brazil get to see certain products, a special import-tax panel, etc, but no-one else does
That's authorization.
Feature flags were invented to enable continuous integration and trunk-based development. Ultimately, they're an alternative to feature branches. If you wouldn't create a git branch for it, you shouldn't create a feature flag for it.
Additionally, you roll out feature flags incrementally and hand control of them to your product team to use to gather user feedback. Beta users, alpha users, individual users or companies. It’s on a case by case basis as feedback is gathered to refine the feature before it goes to general availability.
Another option that is getting popular is to randomly grant access to a certain percentage of users over a series of days to track the rollout and watch for errors/user complaints.
Often, you end up capturing statistics for usage on wrapped features as well.
I recently wrote a small generalised feature to enable us to turn on flags for specific locales, specific user groups, or specific individual users, all specified in JSON strings stored in a DB (and which the backend caches).
Some flags add a function or widget, while other flags add restrictions or change cronjob behaviour. Is this an authorisation or a feature flag system, or neither?
Sounds like it could be a component of the back end for either one.
A complete feature flag system would also need a business-friendly front-end that product managers could use to roll out features and track how many people were using each one. Possibly an A/B testing component as well. And a way of alerting when a flag has been 100% active for X days so it could be removed from the code. Etc.
A complete authorization system would need a front-end focused on understanding who had which capabilities, assigning capabilities to users and categories of users, and probably some sort of capability grouping and inheritance mechanism. Possibly an impersonation ability for the support team. Etc.
Commonly, you will put a feature behind a feature flag, and roll it out locale by locale, or never.
You build a new feature that only works for a certain place, and you turn it on via a feature flag, and then you expand it to new places, also using a feature flag
I guess the question is when do you grant authorization? Before or after the feature has launched in a region?
This is just a different use of the same concept, as I and the article said.
A feature flag grants or denies access to a feature in exactly the same way as authorization - you could have 'feature' attributes in an ABAC system for example, and in fact I'm sure many systems use exactly this to provide feature tiers.
It's just that feature flags are generally used for a different purpose, ie targeted roll-out of new functionality, ie different policy concerns.
So, different uses, different policies, but the same abstraction/concept.
You may very well want to keep both separate if your business requires separation between the people who control software feature flags vs. the people who determine access entitlements.
I'd strongly disagree with the author that permissions are always long-lived -- modern authorization can also be ephemeral, dependent on run-time context[0], and just as fine-grained as feature-flags.
Full disclosure, I think about this topic regularly because I am a maintainer of SpiceDB[1], an open source authorization database.
It's a little silly, but lots of folks aim for the moon when it comes to performance for authorization, but then go on and sprinkle a dozen feature-flag RPCs each adding more and more latency. You should be able to keep feature-flags performant, too: that's why some SpiceDB users collapse checking for authorization and feature-flags into a single round-trip by defining a permission also requires a feature-flag (e.g. permission = admin & has_beta_feature).
It's really encouraging to be working in this space because there are so many epiphanies like the one in the article, but there just hasn't been tooling to make it as obvious until now. We're seeing folks adopt SpiceDB for update graphs and dependency graphs because the resolution of permissions (finding a path through a graph) is similar to solving these problems as well!
I agree, that authorization can be very short lived, however, there’s a subtle distinction between whether something must be short-lived and whether something can be short lived. In authorization, the it’s usually the former.
To the articles main point: eventually consistent and strongly consistent are not similar.
It’s good to recognize the similarity in these two cases, but why stop there?
Edit: there’s a little bit of novelty in recognizing that global predicates implicitly take a global context argument, but that can be similarly reduced to “all context-sensitive processes are implicit functions over their context and any additional parameters”.
I've been thinking about this topic for some time and love that someone else came to the same conclusion!
There are a lot more differences in the requirements for these use cases though, e.g., feature flags products want for more analytics, controlled rollout, etc.; authorization, not so much. Authorization requires access to lots of shared application data/state; feature flags, not so much.
Another area of overlap I see is entitlements/billing, e.g., can this person access this feature based on the plan they've signed up for? I've seen a lot of companies use the same underlying systems for feature flags, authorization, and entitlements (esp at earlier-stage companies and ones with a heavy DIY bent). Is this consistent with what others see/do?
Consistency with what I’ve seen, but it can really end in tears. FF give you unbelievably useful and snappy ways to get what you want… at the cost of losing all track of what the state of the world is. Simple entitlement systems are clear and well modeled… at the cost of being too inflexible to get what you want :)
We use feature flags for entitlements and experiments at $work, it's all accessed through a consistent `hasFlag` API.
Granted, our use is pretty straightforward, you either have access to product $Foo or you don't.
I think with usage based billing, like first 100 messages free, or tier one gets 5MB uploads, tier 2 gets 50MB uploads it becomes harder to have a universal API, you end up having to do some manual checks.
Still haven't really thought this all out but it's an interesting problem.
Edit: also roles can provide entitlements / enable feature flags. So Admin could get every feature, while intern might get only get the analytics_read feature.
You could abstract a whole codebase in a similar fashion. Afterall, what is the difference between storing "bob" as my first name, vs storing whether I have access to the "first_name.place-0.character-b", "first_name.place-1.character-o", and "first_name.place-2.character-b" features or not.
No its not the same concept (Which is what the article actually says, despite the click bait title)
Feature flags - roll this out to 1% of users, randomly selected; roll this out to users with X hardware in Y region, etc.
Authorization - only users of the admin role can edit other users
As a concrete example, you might authorize some cohort of users as admins. Within that cohort you want to vary the UI for your admin app by using a feature flag controlling whether to use the old React app or a new Angular rewrite you are rolling out in tranches.
Conflating these concepts might work in some cases, but doesnt scale. Its like saying pods, services, deployments in k8s are all the same thing just because you haven’t yet seen a use case where the difference matters. Its not hard to imagine a use case where rolling out a feature necessitates tediously duplicating your ACL rules if you’re using ACL to gate rollout of features.
You’re limiting your view of feature flags to a subset of their potential. Also, authorization schemes like attribute based access control (ABAC) can use any arbitrarily dynamic values from the current context. The two concepts overlap immensely.
How is that different? In the first case call the 1% cohort of users in that experiment treatment "Foo". In second, call them "admins". In either case, if the user is in some group, grant them access?
At a high-level yes they are they same. IMO the difference is where the gating happens. Feature flags can be gated on clients or servers, but authorized features must be gated on the backend to prevent leaking sensitive logic/data to clients.
A feature flag in general needs presence on both the frontend and backend because a change may coordinate between the two.
More properly due to frontend caching issues an HTTP request should include a header with the active features, separately from the header containing the auth token. And that gives a first semantic difference: feature flags take effect when the app is updated/reloaded, auth changes take effect immediately.
At my company we use Feature Flags for Licenses, and Authorization for users.
They are absolutely similar concepts, just as different levels.
If a customer wants to buy Analytics for example, it is controlled via a feature flag to enable it for that entire customer. By default all of thier user accounts can then access Analytics.
Then if we want to restrict certain categories of their users from seeing Analytics we can do that at the Authorization level.
Is it possible we could control all of this with one Authorization layer? Yes, probably.
But this lets us have a bit more fine grained control over things.
It might be more that whether the user is authorized to view something or a particular feature is enabled for some user is really mixing concerns the code shouldn’t care about. Really what it cares about is “can the user do this thing”? How the decision is arrived at should be opaque to the code asking that question. It also probably makes it easier to test because you can just tell that section of the code “yes” or “no” through a stub of that permission / feature oracle.
They might not be the exact same concept but they're definitely related. I'd argue feature flags, authorization, and pricing tiers/entitlements all make up modern 'access control' and 'access management'.
It used to be that authz was just roles and permissions assigned to users, or feature flags & entitlements just booleans, but sophisticated systems allow for all kinds of permutations and rules based on attributes, relationships and environment such that the lines between them are blurred and implementations are likely similar.
As others have said, the differences still come down to a handful of factors like correctness, tolerance for error and performance.
(Disclaimer: I'm a founder in this space and spend a lot of time thinking about it at Warrant - https://warrant.dev/ )
There’s a real insight here. At a core level, we simply want to know “can X do Y”. The answer to this could actually come from a feature flag, an experiment, our authorizations / permissions or the product configuration / SKUs we have.
There are important subtleties that mean the same tech isn’t usually a good choice for all of these. But I’m really interested in building something that understands that as a developer I just want to know if X can do Y.
If anyone wants to jam on this hmu. We’re thinking a bunch about this at Prefab.cloud[0]
I have little doubt that you have thought this through, and for your work they are always used in an aidentical fashion and could be collapsed into a single predicate with no visible distinction between teh two use cases in the calling code.
But for many applications, the semantic difference between the two drives different patterns in the calling code, and when that is the case, having an easily visible difference between the two predicates makes the code more readable and prompts people to write it more correctly.
Example: What happens when the answer is "no?" For many bog-standard applications, it's a NOOP. Let's say there's a feature: You can edit a message that has already been sent.
If you are wrapping that in a flag for gradual rollout or early access purposes, you wrap both the client-side edit control and the server-side API endpoint in the "can X do Edit" test, and if the answer is no, you don't show the control in the client, and you 404 the endpoint on the server.
Whereas, if editing messages that have already been sent is a feature only available to a special class of users—let's say they are paying $8 a month for an orange check-mark on Hacker News—then on the client we still hide the control if our user is not authorized to edit messages.
But on the server side, we typically don't want to 404 the endpoint, we want to give some semantically appropriate response such as a 401 "unauthorized" status.
If you use one construct for asking both FF and auth questions, it's hard to see at a glance whether the code is doing an appropriate thing with the answer.
This is grossly oversimplified, but the thesis here is that yes, if you use both FFs and auth in exactly the same way, it's reasonable to consider using one way to ask the question. But the definition of "using them the same way" should also include what you do with the answer.
In your case, you very likely always do exactly the same thing with the answer regardless of whether the answer is derived from FFs or auth. But for those who do different things depending on which question they're answering, I suggest having different ways of asking the questions provides better affordances for writing and maintaining the code.
Amazingly I don't disagree. In my usage the desired return result is two-part. The first is indeed boolean, but there is also a "why". Was it an auth rule? A complex FF? I think the ideal interface would give sufficient context to callers so they could do the right thin with these 401s as you describe.
Granted, the reason I want this is more that I've spent too much time try to help customer support figure out why person X can't see Y, which can devolve into checking 3 different systems too often.
That's a common trap engineers fall into. Just because you found some similarities, doesn't yet mean there's a pattern. Instead of looking for accidental similarities, see if you can spot fundamental differences. Only if you can prove there are none, then you can claim they are the same concept.
Take any SaaS, where a single account can have multiple users. Feature flag is usually an account level concept. Authorization is a user level concept. Just because they both implement a conditional doesn't yet mean they are the same concept.
Ha, I literally used feature flags for authorization when working at (big tech company) since it was very difficult to plumb that data otherwise. The experiment framework was a lot more mature and supported cross stack compared to any other membership checking tooling.
The concept behind feature flags is, "this person will have access to this feature some day, and I (am / am not) ready for them to see it yet." They're shortlived, tend to be sprinkled throughout the codebase, and need to be aggressively removed to prevent a mess. The consequences for failure are usually minor.
The concept behind authorization is, "this person (does / does not) have this capability, and they absolutely must not be given capabilities they don't have." They're long lived, have extraordinary consequences for failure, and need careful design to make sure they're centralized and easy to reason about.
These are vastly different needs that demand different design approaches.