A feature flag that hides a screen or button decides what a user sees. It does not decide what a user can do. The server must still check authorization on every request, whatever the flag says. Treat flags as a rollout tool and keep access control as a separate, always-on layer.
What a permissioning flag is
Martin Fowler's article lists permissioning toggles as a category: flags that change the features or experience certain users receive, such as premium features or an internal beta group. It recommends placing toggle points for per-request categories at the edge services, the publicly exposed web apps where the request first enters your system and the router has the most context.
Placing a toggle point where HTML is rendered is a clean pattern. It also shows the limit: the edge decides what to display.
The failure to avoid
Suppose a premium export feature is hidden behind a plan flag. The button is gone for free users. But the API endpoint behind it checks nothing except that the caller is logged in. Anyone who knows or guesses the URL can call it.
The flag worked as designed. The product shipped with no access control.
This is a standard broken access control pattern, and it hits flagged features often because the feature was built as new work and the team trusted the flag.
A simple division of labor
Use flags to answer: should this user be shown this feature right now? Use authorization to answer: is this user allowed to perform this action on this resource?
Both checks happen, in this order. The server first checks authorization on the request. The flag then controls exposure. If a flag is misconfigured, the worst outcome should be a visible but still protected feature, not an exposed one.
Test it
For every flagged feature that touches data, write a test that calls the endpoint directly with a user who should not have access, with the flag turned on. The test should be refused. Add a second test with the flag off, calling the endpoint anyway. It should also be refused or return nothing useful.
If the second test succeeds in doing the action, an unreleased feature is live for anyone who finds it.
Beware client-side flags
A flag evaluated in the browser is visible to the user. Fowler notes a related risk with per-request overrides: curious or malicious users can modify state. Anything the browser decides, the user can alter. Never rely on a client-side flag to protect data.
A concrete case
Imagine a beta reporting feature shown only to a pilot group through a flag. The API route behind it takes a report ID. If the route checks only that the caller is signed in, any user can read any report by changing the ID. The flag hid the link, nothing more. The fix is an ownership check in the route, which should exist whether or not the flag does.
Review checklist
- Each flagged endpoint has its own authorization check.
- Tests call endpoints directly with the flag in both states.
- Flag evaluation for access-related features happens on the server.
- Unreleased endpoints are not reachable by guessing the path.
- Removing the flag later does not remove a check, because the check never lived in the flag.
Quick check
Is a feature flag an access control?
No. A flag controls exposure. Authorization must be enforced by the server on each request regardless of flag state.
Where should permissioning flags be checked?
At the edge for display decisions, with a separate server-side authorization check on every request that touches data.
Sources
Last reviewed: 19 October 2026.