Blog / Security
RBAC design for a platform managing dozens of clients: what 'least privilege' should mean in practice
Role-based access control sounds like a solved problem — define some roles, assign permissions to each, done. For a platform managing one organization, that's mostly true. For an MSP platform managing dozens of separate client organizations through one set of technicians, 'least privilege' has an extra dimension that generic RBAC guidance usually skips: privilege isn't just about what a role can do, it's about which tenant a role can do it to, and getting that second dimension wrong is a much larger blast radius than getting the first one wrong.
A technician who's over-permissioned within one client's environment is a bounded problem — bad, but contained. A technician whose role permissions apply across every client tenant by default, because the RBAC model was built role-first without a tenant-scoping layer underneath it, turns one compromised or careless account into a cross-client incident. That's the failure mode that matters most for MSP tooling specifically, and it's the one generic 'we support RBAC' marketing copy almost never addresses.
What tenant-aware least privilege actually requires
- Per-tenant role assignment, not global roles — a technician being an 'admin' needs to mean admin for the specific clients they're assigned to, not admin everywhere by default with tenant restriction as an afterthought.
- Enforcement below the application layer, not just in it — role checks in application code are necessary but not sufficient; if a bug or an overlooked code path skips the check, a database that doesn't independently enforce tenant boundaries has no second layer to catch it.
- Scoped API and integration credentials — a Microsoft 365 or firewall integration credential for one client shouldn't be reachable or reusable in the context of a different client's tenant, even by someone with legitimate cross-tenant platform access.
- Auditable role changes — who granted which technician access to which client, and when, needs to be a queryable record, not something reconstructed from memory during a client's security questionnaire.
The second bullet is worth dwelling on because it's the one most platforms skip. Application-level tenant filtering is the obvious layer to build — it's where the business logic already lives — but it's also the layer most likely to have a gap somewhere, because it's re-implemented in every query, every route, every report. A second, independent enforcement layer that doesn't trust the application code to have gotten every path right is what actually closes that gap, and it's a meaningfully different engineering commitment than 'we filter by tenant in our queries.'
This is where Nexus's own architecture is concrete rather than aspirational: tenant isolation is enforced at two independent layers — application-level filtering and PostgreSQL row-level security at the database itself, keyed per tenant — so a gap in the first layer isn't the only thing standing between one client's data and another's. Role and permission granularity on top of that isolation layer is an area we keep refining as the platform's own technician base and client count grow; if you're evaluating any MSP platform's RBAC claims, including ours, the concrete question to ask isn't 'do you have RBAC' — it's 'show me what happens if your application-layer tenant check has a bug in it.' A vendor with a real second layer can answer that question with an architecture diagram. One without it usually changes the subject.