# RBAC for Development Teams: A Practical Guide
Access control is one of those things nobody thinks about until the day a junior engineer accidentally deletes a production database, or an offboarded contractor still has a valid API token three months later. Role-based access control (RBAC) is the model most platforms use to prevent exactly these situations. This guide explains how RBAC works in practice for a software team and how to model it without drowning in policy files.
What RBAC actually is
RBAC assigns permissions to roles, and roles to users — rather than assigning permissions directly to individuals. The indirection is the whole point. When someone joins the team, you grant them a role. When they leave, you remove it. You never have to audit a sprawling list of per-user grants.
The three core nouns:
- Subject — the user or service account taking an action.
- Role — a named bundle of permissions (e.g.
admin,member). - Permission — the right to perform an action on a resource (e.g.
deployment:create,database:delete).
RBAC is distinct from ABAC (attribute-based access control), where decisions depend on attributes like time of day, IP range, or resource tags. ABAC is more expressive but much harder to reason about. For most engineering teams, RBAC with a handful of well-chosen roles covers 95% of needs.
A sane default role model
Most developer platforms — PandaStack included — converge on a small set of organization roles:
| Role | Can do | Cannot do |
|---|---|---|
| Owner | Everything, including billing, deleting the org, transferring ownership | — |
| Admin | Manage members, create/delete projects, manage env vars and domains | Delete the org, change billing owner |
| Member | Deploy, view logs/metrics, manage their own projects | Invite/remove members, change billing |
Three roles sound too simple, and that is exactly why it works. The temptation is to invent senior-member, read-only-auditor, deploy-only-bot, and so on. Resist it until you have a concrete, repeated need. Every extra role is a thing someone has to understand at 2am during an incident.
The principle of least privilege
The guiding rule is least privilege: grant the minimum access required to do the job, nothing more. Practically:
- New hires start as
member, notadmin. - Service accounts (CI tokens, bots) get scoped tokens, never a human's credentials.
- Billing and org deletion stay with
owneronly — ideally two owners so you are not locked out if one leaves.
Least privilege is not about distrust. It limits blast radius. If a member's laptop is compromised, the attacker cannot wipe the org or exfiltrate the billing details.
Scoping permissions: org, team, project
Flat org-wide roles break down once you have multiple teams. The fix is scoped roles — a person can be an admin of the Payments team's projects but only a member elsewhere. A useful hierarchy:
Organization
├── Team: Payments
│ ├── Project: checkout-api
│ └── Project: invoicing-cron
└── Team: Growth
├── Project: marketing-site
└── Project: analytics-pipelineGrant roles at the level that matches responsibility. A platform engineer might be an org admin; a feature team lead is a team admin; an IC is a project member. On PandaStack, teams and orgs map directly to this model, with owner/admin/member roles applied per scope.
Tokens and service accounts
Humans are only half the story. Most security incidents involve long-lived credentials that outlive their purpose. Rules of thumb:
- Prefer short-lived tokens that rotate automatically over static API keys.
- Give CI/CD its own service identity with deploy-only scope — it should not be able to delete databases or read billing.
- Audit tokens quarterly. Anything not used in 90 days gets revoked.
# A scoped deploy token should be able to do this...
curl -X POST https://api.example.com/v1/projects/checkout-api/deploy \
-H "Authorization: Bearer $DEPLOY_TOKEN"
# ...but NOT this:
curl -X DELETE https://api.example.com/v1/databases/prod-db \
-H "Authorization: Bearer $DEPLOY_TOKEN"
# -> 403 ForbiddenAuditing and reviews
RBAC is not set-and-forget. Schedule a quarterly access review:
- 1List every member and their role.
- 2Confirm each role still matches the person's responsibilities.
- 3Revoke access for anyone who changed teams or left.
- 4Rotate or delete unused tokens.
Keep an audit log of who changed what and when. When an incident happens, the first question is always "who had access and what did they do?" — and you want a real answer, not a guess.
Common mistakes
- Everyone is an admin. The fastest way to a 3am disaster. Default to
member. - One shared login. You lose all attribution. Always use individual accounts plus SSO.
- Orphaned tokens. Generated for a one-off script in 2024, still valid today.
- Over-engineering roles. Ten custom roles nobody understands is worse than three everyone does.
- No offboarding checklist. Removing org access should also revoke tokens and SSO sessions.
How this looks on PandaStack
PandaStack ships RBAC with owner, admin, and member roles applied across organizations and teams, so you can model the org/team/project hierarchy above without writing policy files. Combined with SSO for centralized identity, offboarding becomes a single action in your identity provider rather than a manual hunt across services.
References
- [NIST RBAC standard (INCITS 359)](https://csrc.nist.gov/projects/role-based-access-control)
- [OWASP Authorization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html)
- [Kubernetes RBAC documentation](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)
- [AWS IAM least-privilege guidance](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)
---
RBAC done well is invisible: the right people can ship, the wrong actions are blocked, and offboarding takes seconds. If you want this baked in rather than bolted on, PandaStack includes team/org RBAC on every plan, including the free tier — spin up an org at [dashboard.pandastack.io](https://dashboard.pandastack.io).