Retool's permission system has been rebuilt from the ground up, and we are rolling this change out to cloud organisations as of August 2026. When you go to yourInstanceURL/settings/roles and see the below, that means you are on the new permissions model
The biggest conceptual shift in the new permissions model is that object permissions and organisation permissions are genuinely separate systems, not two flavours of the same thing.
Object permissions cover
apps,
resources,
workflows,
agents, and
Backend Functions (Backend Functions is a fifth object type, specific to the new app builder. It governs access to Functions, the TypeScript backend logic layer of apps built there).
They are graded: Own beats Edit beats Use beats no access. No access is never stored as a row; it is simply the absence of one.
organisation permissions cover settings pages such as source control, audit log, and billing. These are boolean. You either have the scope, or you don't. There are no levels to compare.
Reasoning about "how much access" only applies to objects. Organisation permissions are a yes or no switch.
Example from above: Tom can edit the Sales Dashboard app and edit the Prod Postgres resource. Same role, App-and-Resource-Editor, both times, its scopes never change, but each grant hands that role a different object to attach to.
If you are a visual learner the following chart may be helpful for your understanding of the core terms
A role defines an access level and, for object roles, whether that access is fixed to every object of a type or left open to whichever objects you choose later when you link the objects to the role. It does not define who gets that access. That is the subject's job, and a subject can be a user, a group, or a pending invite.
In Retool this is updated on /settings/roles path
Creating an Object role:
Creating a universal, non object role:
Subject: who's allowed
A subject is whoever is on the receiving end of a grant, a user, a group, or a pending invite. But the model doesn't require a group in between, a role can be granted straight to a single user or to a pending invite just as easily.
In Retool you assign the role to the subject group in /settings/groups/uuid:
This is the single most important fact to internalise, and the easiest one to miss. Universal versus Individual is a property of the role itself.
Universal: the role covers every object of that type in the org, including ones created after the role was set up. Good for a platform team that manages all resources.
Individual: the role covers only the specific objects or folders you pick each time you assign it. The role sets the access level; the assignment sets what it applies to. This is what you see in the example above where the individual object is assigned to the subject group
A single role cannot be Universal for one group and Individual for another. If you need both behaviours, you need two separate roles. One added nuance worth knowing: this grant type is set per object type within a role. A role that touches both apps and resources could apply Universal to apps and Individual to resources, since each object type carries its own toggle. Here is an example of this
Under the hood, this shows up as which bucket of scopes a role draws from. A role that grants Individual access to apps carries a plain scope like apps_access:edit. A role that grants Universal access to apps carries a differently named scope, universal_apps_access:edit, and that scope actually lives alongside the organisation level settings scopes, not with the object scopes. This is a little counterintuitive: something that is clearly about objects (editing apps) is technically stored as an organisation scope once it is Universal. A role assigned this way needs no object id at all, since the scope already says "all of them." A role built from the plain, non-universal scopes does need an object id on each assignment, since the scope alone does not say which object it applies to. The one grant type per role per object type rule you see in the product follows directly from this: a role is simply built from one bucket of scopes or the other for a given object type; it is not a separate toggle sitting on top.
Two related rules worth knowing:
You cannot grant Own without also granting Edit and View and you cannot grant Edit without also granting View. Scope dependencies like this are checked and enforced when a role is created, so a role can never end up in an inconsistent state.
When checking a user's access, the system automatically expands to every group that user belongs to and evaluates all of their grants together, then returns the single highest access level found across all of them. Archived groups are excluded from this expansion. [This is something that we are not reflecting in the UI yet, but we are working on it - you will see all grants and can therefore see an app twice each time with a different permission scope which is confusing]
The Assignment step, picking specific objects or folders, only comes into play for Individual roles. Universal roles skip it entirely because there is nothing left to choose.
Direct access and role-based access stack; they never override
You can still configure access directly on a group's page (per object type), separately from any role. Direct access and role-based access are additive. If a group has Use through direct configuration and Edit through a role on the same object, the group ends up with Edit. Higher access always wins. Nothing subtracts or overrides. This is a real architectural choice; having two coexisting mechanisms for the same outcome is legitimately more complex than having one, and it is worth understanding rather than treating as a documentation gap.
You can assign universal roles to users in settings/users -> Go to user -> organisation permissions tab
This is not possible with object scopes.
As mentioned above, to add an object to a role grant you go to /settings/groups/uuid -> Object Permission tab -> click Add Object -> select a role
This will then show as a Directly assigned object as you can see here for App C
Scoping an Individual object role to a folder applies it to everything in that folder, including objects added later. There is no separate grant created for each item inside; the folder-level grant is simply checked against the child object at access time. Moving an object into a different folder means it now inherits that new folder's permissions instead of its old one.
Personal folders are a hard boundary
Personal folders are an exception to every rule above. Only the folder's owner and members of the Admin group can access what is inside a personal folder. Every role grant is bypassed here, including Universal ones. A role that grants Universal Edit on all apps still will not give someone access into another user's personal folder.
Plan and default role limits
organisation roles with sensitive scopes (SSO, billing, IAM, audit log, source control) require an Enterprise plan. A Business plan only exposes non-sensitive scopes: query library, draft apps, themes, Assist, user visibility.
Object roles overall are Enterprise only.
Default object roles (the ones auto-created for Admins, Editors, Viewers) can only ever be assigned to their matching default group. You cannot take the Admin universal object role and hand it to a custom group.
A deeper dive into what these changes look like on your main storage DB (self hosted)
The following is more applicable to self-hosted customers as Retool manages cloud instancesβ main storage DB.
The old system: nine plus tables, one purpose each
Before this update, permissions lived across a sprawling set of tables: groups, group pages, group resources, group workflows, role screens, group folder defaults, group resource folder defaults, role pages members, and user role folders. Each table handled one narrow slice of access. Understanding a single group's real permissions meant checking several places at once.
The new system: two tables, one shared model
Everything now runs through two concepts/tables:
Roles, named bundles of permission scopes
Role grants, the link between a role and a subject, optionally scoped to one object
For example
In the roles table RoleId 46ac688β¦ holds own access to apps: it carries apps_access:own (+ edit + view), so a subject granted this role on an app can view and edit it
Querying the role_grants table for this user returns 1 result: role 46ac6884β¦ granted directly to user 1,319,983 on app 3458233. One row = one direct grant = own access to that single app. Any other access this user has comes from their groups, which live in separate rows keyed by subjectGroupId.**