Guides
Retool Environment Permissions: Workarounds That Work
If you've set up multiple environments in Retool — say, one pointing at your production database and another at QA — you've probably run into the same wall: there's no built-in way to set Retool environment permissions per user or group. A support user shouldn't be touching production data, and a QA engineer doesn't need prod access. But out of the box, Retool lets any user switch environments freely. This guide covers what's actually available today and the most reliable workaround to lock down environment access by user group.
Why Retool Doesn't Support Per-Environment Permissions Yet
As of now, Retool's permission model operates at the app and resource level — not the environment level. You can control who can edit an app versus who can only view it, and you can restrict access to specific resources. But there's no native toggle that says "this user group can only use the staging environment" or "block viewers from switching to production." This is a highly requested feature and is on Retool's roadmap, but it's described internally as "a large lift" — meaning it's coming, but not immediately. Until then, you need a workaround.
The Core Problem: Environment Switching Is Open to All Viewers
By default, Retool exposes an environment switcher dropdown inside apps, and users can also manipulate the active environment directly via the _environment URL query parameter. This means even a read-only viewer could switch from your staging environment to production and interact with live data — which is a real risk if your app writes, updates, or deletes records.
The Recommended Workaround: Group-Based Visibility + Query Guards
The most practical approach combines Retool's user groups with conditional logic on containers and query transformers. Here's how to implement it step by step.
Step-by-Step: Restricting Environment Access by User Group
- Step 1 — Create a user group for environment access. In your Retool org settings, create a group for users who are permitted to access production. For example, name it
production_users. Assign only the appropriate team members (e.g. senior support staff, release engineers) to this group. - Step 2 — Wrap sensitive UI in a Container component. In your Retool app, place all production-sensitive components (tables, forms, action buttons) inside a
Containercomponent. - Step 3 — Set the Container's Hidden property using JS. In the Container's
Hiddenfield, add the following expression:{{ retoolContext.environment === 'production' && !current_user.groups.find(group => group.name == 'production_users') }}. This hides the container when the active environment is production and the current user is not in theproduction_usersgroup. - Step 4 — Add a user-facing message. Create a separate component (a Text component works fine) that displays a message like "You don't have permission to manage production data." Set its visibility to show only when the same condition is true. This gives non-permitted users clear feedback instead of a blank screen.
- Step 5 — Secure your queries with transformer guards (critical). The
Hiddenproperty is evaluated in the browser, which means a technically savvy user could bypass it using browser dev tools. To actually secure the data layer, add a transformer to each sensitive query. Inside the transformer, check the same group condition and either return an empty result or throw an error if the user shouldn't have access:if (retoolContext.environment === 'production' && !current_user.groups.find(g => g.name === 'production_users')) { throw new Error('Access denied'); } return data;
Is This Approach Actually Secure?
Partially — and it's important to understand the boundary. The Hidden property on a container is evaluated in the browser, inside a sandboxed iframe. It prevents casual access but is not a hard security boundary on its own. Query transformers and JavaScript queries in Retool are also executed in the browser, not on the server. This means the real security layer must be your backend — your database, API, or resource-level permissions should enforce who can read or write production data regardless of what the Retool app allows. Retool's JS sandbox prevents access to document and sends requests from null origins, but it does not replace server-side authorization.
What About the Environment Dropdown in the App?
Users with viewer access will still see the environment switcher and can change it. You cannot fully remove the production option from the dropdown for specific users today. The best you can do is let them switch — but ensure that switching to production without the right group membership either hides all sensitive UI or surfaces a clear "access denied" message, and that your backend rejects any unauthorized queries regardless.
Summary: What to Do Right Now
- Use Retool user groups (e.g.
production_users) to segment users by environment access intent. - Use
retoolContext.environmentandcurrent_user.groupstogether to conditionally hide UI containers. - Add transformer-level guards to every sensitive query as a secondary layer of protection.
- Rely on your backend resource permissions as the true security enforcement layer — Retool's JS runs in the browser.
- Display a clear message to unauthorized users rather than silently hiding content.
This isn't a perfect solution — native Retool environment permissions per user group would be far cleaner — but it's the most robust approach available today. If you're building internal tools where environment access control is critical, pairing this workaround with strict resource-level database permissions is non-negotiable. Watch the original Retool community thread for updates when the native feature ships.
Ready to build?
We scope, design, and ship your Retool app — fast.