Back to Blog
Guide7 min read2026-05-01

RBAC: Role-Based Access Control Explained with Examples

Understand role-based access control from first principles and learn how to implement it correctly in your applications and teams.

RBAC: Role-Based Access Control Explained with Examples

Access control is the backbone of application security. Get it wrong and the consequences range from data leaks to complete account takeovers. Role-Based Access Control (RBAC) is the most widely adopted model for managing who can do what in an application — and for good reason: it maps well to how organizations actually work.

This guide explains RBAC from first principles, with practical examples for both application implementation and team management.

What Is RBAC?

RBAC assigns permissions to roles, and roles to users. Rather than granting permissions directly to individual users, you define roles (e.g., Admin, Editor, Viewer) with specific permissions, then assign users to those roles.

The three core concepts:

  • User — a person or service account
  • Role — a named collection of permissions
  • Permission — the ability to perform a specific action on a specific resource

Why RBAC Over Direct Permission Assignment?

Imagine a team of 50 engineers. If you assign permissions directly to users, every onboarding/offboarding operation requires auditing and modifying individual permission lists. With RBAC, you assign a role — done.

Benefits:

  • Easier onboarding: assign a role, not 30 individual permissions
  • Easier offboarding: remove role, access is revoked
  • Easier auditing: review roles, not individual user permissions
  • Principle of least privilege: roles grant only what's needed

Step 1: Define Your Permission Model

Start by identifying your resources and actions:

Resources: projects, databases, cronjobs, deployments, billing, team_members
Actions: create, read, update, delete, deploy, view_logs

Then define which combinations make sense as roles.

Step 2: Design Your Roles

A practical role hierarchy for a cloud platform:

RolePermissions
OwnerAll permissions including billing and team management
AdminDeploy, manage resources, manage members (not billing)
MemberView and use resources, create deployments
ViewerRead-only access to all resources

Start with broad roles. Add granularity only when a real use case demands it.

Step 3: Implement RBAC in Your Application

// Role definitions
const ROLES = {
  owner:  ['projects:*', 'databases:*', 'billing:*', 'team:*'],
  admin:  ['projects:*', 'databases:*', 'team:read', 'team:invite'],
  member: ['projects:read', 'projects:deploy', 'databases:read'],
  viewer: ['projects:read', 'databases:read'],
};

// Check permission middleware
function requirePermission(permission) {
  return (req, res, next) => {
    const userRole = req.user.role;
    const permissions = ROLES[userRole] || [];
    const hasAccess = permissions.some(p =>
      p === permission || p === permission.split(':')[0] + ':*'
    );
    if (!hasAccess) return res.status(403).json({ error: 'Forbidden' });
    next();
  };
}

// Usage
app.delete('/api/projects/:id',
  authenticate,
  requirePermission('projects:delete'),
  deleteProjectHandler
);

Step 4: Store Roles in Your Database

CREATE TABLE organization_members (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES users(id),
  organization_id UUID NOT NULL REFERENCES organizations(id),
  role TEXT NOT NULL CHECK (role IN ('owner', 'admin', 'member', 'viewer')),
  created_at TIMESTAMP DEFAULT NOW(),
  UNIQUE (user_id, organization_id)
);

Query role on every request — don't rely on the JWT payload alone, as roles may change between token issuance and use.

Step 5: Enforce at the API Layer, Not Just the UI

A common mistake is hiding UI elements for unauthorized users but forgetting to enforce permissions on the API. Both layers must check:

// Frontend: hide the button
{user.role === 'owner' && <DeleteButton />}

// Backend: enforce on the API (always required)
app.delete('/api/projects/:id', requirePermission('projects:delete'), handler);

Frontend checks improve UX. Backend checks provide actual security.

Step 6: Audit Role Changes

Log every role assignment and revocation:

await AuditLog.create({
  action: 'role_changed',
  performedBy: req.user.id,
  targetUser: targetUserId,
  oldRole: member.role,
  newRole: newRole,
  timestamp: new Date(),
});

RBAC on PandaStack

PandaStack implements RBAC natively across all teams and organizations. You get three built-in roles — Owner, Admin, and Member — with well-defined permissions for every resource: container deployments, databases, cronjobs, edge functions, and more.

Manage team members and roles from the dashboard:

npm install -g @pandastack/cli
panda team:invite user@example.com --role member
panda team:role user@example.com --role admin

Or manage everything visually at [dashboard.pandastack.io](https://dashboard.pandastack.io).

Summary

RBAC simplifies access management by separating permissions from individual users. Design roles that map to real job functions, enforce permissions at the API layer, store roles in your database, and audit every change. For platform-level RBAC without building it yourself, see [docs.pandastack.io](https://docs.pandastack.io).

Ready to deploy?

Start free on PandaStack — no credit card required.

Start free on PandaStack

More in Guide

Browse all Guide articles →

See also