Permissions, flags and failures Recommended
Read feature flags before the first paint
Decide feature flags on the server and send them with the first page or data load. A flagged feature then never flashes in or out. The API checks the same flag.
How to do it
Follow deploy is not release for how flags work. Evaluate them per user on the server, for example with an OpenFeature provider, and pass the results to the client. A flagged API route checks the flag too, so a hidden button is no way around it. Remove flags when they are done, as stale flags describes.
Example
@app.get("/api/session")
def session_info():
user = current_user()
return {
"user": {"id": user.id, "name": user.display_name},
"flags": {"newReports": flags.is_enabled("new-reports", user=user, default=False)},
}
const session = await api.get('/api/session');
const app = createApp({ flags: session.flags });
if (session.flags.newReports) app.addRoute({ path: '/reports', load: () => import('./reports/ReportsScreen') });
How to check
A browser test loads the screen with the flag off and records every frame for one second. The flagged control never appears. A direct API call to the flagged route gets 404.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers app interface playbook: https://agentwranglers.se/playbook/app-ui/permissions-flags-and-failures/feature-flags-in-ui.