← All schemas
Schema Library

RBAC Database Schema

Role-based access control resolves one question: does this user have this permission right now. The schema answers it with seven tables. Users join organizations through memberships; roles are scoped to an organization; permissions are global resource-plus-action pairs; membership_roles grants a membership a role; role_permissions grants a role its permissions. A permission check is then a three-join path: membership -> membership_roles -> role_permissions -> permissions. The deliberate choice is org-scoped roles: permission names stay tenant-free, so the same role definitions (admin, editor, viewer) can be re-created per organization without any tenant column on the permission table itself.

Last updated: 2026-09-27

Source: Original design by dbdiagramr, following the canonical RBAC model

Tables
7
Check path
Membership -> Role -> Permission
Join tables
2
Mini Map
Open in DBdiagramr to edit →

Tables in the RBAC schema

ColumnTypeNullableKey
organizations
iduuidNoPK
namevarcharNo-
slugvarcharNo-
created_attimestamptzNo-
users
iduuidNoPK
emailvarcharNo-
namevarcharYes-
created_attimestamptzNo-
memberships
iduuidNoPK
organization_iduuidNo-
user_iduuidNo-
joined_attimestamptzNo-
roles
iduuidNoPK
organization_iduuidNo-
namevarcharNo-
descriptiontextYes-
permissions
iduuidNoPK
resourcevarcharNo-
actionvarcharNo-
descriptiontextYes-
membership_roles
membership_iduuidNo-
role_iduuidNo-
granted_attimestamptzNo-
role_permissions
role_iduuidNo-
permission_iduuidNo-

Frequently asked questions

What tables does an RBAC database schema need?

An org-scoped RBAC schema needs organizations, users, memberships, roles, permissions, membership_roles, and role_permissions - 7 tables. The two join tables carry the many-to-many edges between memberships and roles, and between roles and permissions.

How do you check a permission in SQL with this schema?

Join from the user's membership through membership_roles to the role, then through role_permissions to permissions, filtering on resource and action: SELECT 1 FROM memberships m JOIN membership_roles mr ON mr.membership_id = m.id JOIN role_permissions rp ON rp.role_id = mr.role_id JOIN permissions p ON p.id = rp.permission_id WHERE m.user_id = ? AND m.organization_id = ? AND p.resource = 'articles' AND p.action = 'delete'.

Should roles or permissions be scoped to the organization?

Scope roles to the organization and keep permissions global. Permissions are vocabulary (resource + action pairs like articles:delete); roles are the org's policy (which permissions admin means here). This keeps permission names stable while each tenant defines its own roles.

Explore more schemas

Visualize your own database

Paste your PostgreSQL connection string and get an interactive ER diagram of your own schema in under 10 seconds. No signup required.

Try it free →