diagram.mmd — er
Role Hierarchy Structure er diagram

A role hierarchy is the data model underlying a Role-Based Access Control system. Understanding the entity relationships helps developers design databases, API schemas, and authorization logic that scales from simple three-role systems to complex multi-tenant enterprise setups with hundreds of roles and thousands of permissions.

The foundational entities are User, Role, and Permission. The relationship between User and Role is many-to-many: a user can hold multiple roles (e.g., both editor and billing-viewer), and a role can be assigned to many users. This is modeled as a join table (user_roles). Similarly, Role and Permission have a many-to-many relationship modeled as role_permissions.

A permission represents a granular capability, typically expressed as a resource:action pair — invoices:read, invoices:write, admin:access. Grouping permissions into roles allows you to reason about access at a human-meaningful level.

Role hierarchies add another layer: roles can inherit from parent roles. A super-admin role might be defined as a child of admin, automatically inheriting all of admin's permissions plus having additional ones. This inheritance is modeled as a self-referential role_parents relationship on the Role entity, forming a directed acyclic graph.

In multi-tenant systems, a Tenant entity scopes everything: roles are defined per tenant, users belong to tenants, and permission checks always include the tenant context. This prevents one tenant's users from accessing another tenant's resources even if they hold the same role name. The runtime enforcement of this structure is shown in RBAC Authorization Model and Access Control Decision Flow.

Free online editor
Edit this diagram in Graphlet
Fork, modify, and export to SVG or PNG. No sign-up required.
Open in Graphlet →

Frequently asked questions

A role hierarchy extends the basic RBAC model by allowing roles to inherit permissions from parent roles. A `super-admin` role can be defined as a child of `admin`, automatically inheriting all admin permissions plus having additional ones. This inheritance is modeled as a directed acyclic graph via a self-referential relationship on the Role entity.
The core tables are User, Role, and Permission, with `user_roles` and `role_permissions` as many-to-many join tables. Role inheritance uses a `role_parents` table with `child_role_id` and `parent_role_id` columns, forming the DAG. Permission resolution requires traversing this graph upward from the assigned role to all ancestor roles and collecting the union of permissions.
Every entity gains a `tenant_id` foreign key. Roles, permissions, and user-role assignments are all scoped to a specific tenant. This ensures that Tenant A's `admin` role is entirely separate from Tenant B's `admin` role in both definition and assignment. All authorization queries must include the tenant context to prevent cross-tenant access.
For deep hierarchies, computing the full permission set requires recursive queries or in-memory graph traversal on each request. Common mitigations include caching the resolved permission set per user (invalidating it when roles or permissions change), denormalising the effective permissions into a flat permissions table, or embedding the resolved permissions in a JWT so the resource server does not need to query the database at all.
mermaid
erDiagram USER { uuid id PK string email string name timestamp created_at } ROLE { uuid id PK string name string description uuid tenant_id FK } PERMISSION { uuid id PK string resource string action string description } TENANT { uuid id PK string name string slug } USER_ROLE { uuid user_id FK uuid role_id FK timestamp assigned_at } ROLE_PERMISSION { uuid role_id FK uuid permission_id FK } ROLE_PARENT { uuid child_role_id FK uuid parent_role_id FK } USER ||--o{ USER_ROLE : "assigned" ROLE ||--o{ USER_ROLE : "held by" ROLE ||--o{ ROLE_PERMISSION : "grants" PERMISSION ||--o{ ROLE_PERMISSION : "granted via" ROLE ||--o{ ROLE_PARENT : "inherits from" ROLE ||--o{ ROLE_PARENT : "parent of" TENANT ||--o{ ROLE : "owns"
Copied to clipboard