Yashveer Singh
Connect
<- All posts
Security, Auth, and Compliance12 min read

The Permission System That Scales With Your B2B Customers

A B2B permission system that scales requires a layered model: system roles, organization roles, and resource-level permissions. Flat role lists collapse under enterprise requirements. I build these with RBAC as the baseline, ABAC for attribute-driven rules, and a clear separation between platform-level and customer-configurable permissions. That combination handles the first customer and the fiftieth without a rewrite.

Written by Yashveer Singh, founder of Yashveer Labs.

What you actually need to know

  • Flat role systems break at the first enterprise customer who needs custom roles. Build a role-permission join from the start.
  • Multi-org context is not optional. Every permission check must carry user ID, org ID, and resource.
  • RBAC handles 80 percent of B2B use cases. ABAC is the layer for attribute-driven rules that enterprise contracts demand.
  • Customer-configurable roles need a boundary. Customers customize within what you define, not outside it.
  • Audit logs on every permission change are the difference between passing and failing a vendor security review.
  • In my experience, the teams that get permission systems right write down the data model before the first line of code.
ApproachFlexibilityComplexityBest for
Flat roles (admin/member/viewer)LowLowEarly stage, single product
RBAC with join tableMediumMediumMost B2B SaaS at scale
ABAC with attribute rulesHighHighRegulated industries, enterprise contracts
ReBAC (relationship-based)Very highVery highGraph-structured data, document hierarchies

The core argument

The permission system is the product feature that gets the least love and causes the most enterprise sales friction. Every founder I talk to has a version of this story: a mid-market deal was moving until the security questionnaire asked about custom roles. The current system has three hard-coded roles. The buyer needs seven. The deal pauses. The team scrambles. The re-architecture takes a quarter.

The reason this happens is that most early permission systems are built for the first customer, not the tenth. Three roles is a fine start. The mistake is the data model underneath. If permissions are if-statements on role strings scattered across the codebase, adding a fourth role means touching every one of those statements. If permissions are rows in a join table between roles and permission constants, adding a fourth role is one database insert.

The second thing that breaks is the multi-org model. Early B2B apps often store a single role per user. The user is an admin or they are not. Then the first customer wants a user to be an admin in their account and a read-only viewer in a partner account. Now the data model needs an org context column on the role, which means the permission check needs to carry that context on every request.

Both of these problems have the same fix: a principled data model written before the first enterprise conversation. Role-permission joins. Org-scoped assignments. Deny by default. This is not over-engineering. It is the minimum viable permission architecture for anything that will talk to enterprise buyers.

The data model that actually scales

The core tables

Three tables handle most B2B permission needs. A permissions table enumerating every named permission in the system. A roles table with platform-defined and customer-defined roles. A role-permissions join table connecting the two. A user-org-roles table assigning a user to a role within an org context.

The permissions table is the authority. It lists every permission as a constant string, something like reports:export or users:invite. No permissions exist that are not in this table. This is what makes audit logging complete and what makes security reviews tractable.

Platform roles versus customer roles

Platform roles are defined by you and cannot be modified by customers. They cover the cases every org needs: org admin, billing contact, read-only viewer. Customer roles are scopes that the org admin can define within the permission set you expose. The org admin can create a role called "Regional Manager" and assign it reports:export and users:view. They cannot assign it billing:manage if you have not surfaced that permission for customer-configurable roles.

This boundary is the important part. Enterprise buyers want flexibility. They do not want to break their own data. The boundary protects both of you.

ABAC for the rules you cannot express in roles

Some enterprise requirements cannot be expressed in a role. "Only users with department=Finance can export revenue reports." That is an attribute rule, not a role. ABAC adds an attribute evaluation layer on top of the RBAC base. The check becomes: does this user have the reports:export permission via their role, and do their attributes satisfy the policy attached to this resource?

I build this as a policy engine that evaluates at request time. Simple policies can live in a database table. Complex policies warrant a dedicated service or a library like Open Policy Agent.

What it requires

RequirementWithout itWith it
Role-permission join tableRoles are hard-coded stringsAdding roles is one insert
Org-scoped user-role assignmentsUsers have one global roleMulti-org memberships work correctly
Permission constants tablePermissions exist implicitlyAudit log is complete and queryable
Customer role configuration UIEvery new role needs an engineerEnterprise admins manage their own access
Audit log on permission changesIncidents are unrecoverableVendor security reviews are passable

What to look for in a permission system implementation

  • A deny-by-default posture. Explicit grants only.
  • Permission constants defined in one authoritative place, not scattered as strings.
  • Org context on every permission check. No global user-level permissions for resource access.
  • A customer role configuration interface that exposes only the permissions you intend to expose.
  • Audit log rows for every permission grant and revoke. Immutable, with actor and timestamp.
  • A test harness that exercises the permission model on every deploy. Silent regressions in auth are dangerous.
  • A clear escalation path for permission errors. Users should see a clear "access denied" with a path to request access, not a generic 500.

Expert opinion

The teams that build scalable B2B permission systems in the first sprint rarely regret it. The teams that defer it to "when we get an enterprise customer" are rebuilding it under a sales deadline, which is the worst possible time to redesign a data model. The data model cost is one sprint. The re-architecture cost under pressure is two to four quarters of distraction.

>

Yashveer Singh, founder of Yashveer Labs

How this played out on a real project

A client came to me mid-deal with a manufacturing enterprise. Their permission model was three enum values on a users table. The enterprise buyer needed department-scoped permissions, a read-only auditor role, and a custom export role for compliance staff. None of that was possible without a rewrite.

We shipped the new data model in six weeks. Role-permission joins, org-scoped assignments, a customer role configuration page, and an audit log. The deal closed. The model has handled four more enterprise customers without modification since then.

The first thing we did was write the permission constants to a table. Forty-three constants covering every action in the product. That table became the source of truth for the customer configuration UI, the audit log, and the test harness. The rest followed from that one decision.

For the related auth layer, see API authentication in 2026 for how authentication feeds into permission checks, and the user impersonation feature building it securely for the specific case of admin impersonation inside a B2B permission model. The compliance frame for what enterprise buyers actually ask is covered in the security gap how one missing SOC 2 control kills your enterprise deal.

Common mistakes

  1. Hard-coding role checks as if-statements throughout the codebase instead of a centralized permission check.
  2. No org context on permission checks. The user is an admin globally, which breaks multi-org memberships.
  3. Customer-configurable roles with no permission boundary. The org admin can grant billing access to anyone.
  4. No audit log on permission changes. An incident produces zero forensic evidence.
  5. Permissions as string literals scattered across five files. Changing the constant name becomes a search-and-replace incident.
  6. Deny-by-default forgotten. New users get too much access until someone notices.
  7. No test coverage on the permission model. A refactor silently breaks access control.
  8. Building custom ABAC before the RBAC model is stable. Complexity compounds on an unstable foundation.

A 30 day plan

  1. Week one. Write every action in your product to a permissions table. Group by resource type. This is the authoritative list.
  2. Week two. Build the role-permission join model. Migrate any existing hard-coded role checks to query the join table. Add org context to user-role assignments.
  3. Week three. Build the audit log. Every permission grant and revoke writes a row. Add the customer role configuration UI restricted to the permissions you expose.
  4. Week four. Write a test harness that exercises every permission constant. Run it in CI. Pick the next highest-risk gap and plan the next sprint.

For deeper reading, the threat model how to build one in two hours covers the broader security posture exercise, and vendor security assessments how to pass them quickly covers what enterprise buyers actually evaluate when they review your access control model.

FAQ

Frequently asked

Author

The reason I write these

I write these because the writing is the proof. Yashveer Singh, founder of Yashveer Labs. The systems I build are not theoretical. They are running right now, serving real users, generating real revenue. That is the bar I hold this writing to. If you want to hire someone who can match that bar, I am the call.

Related reading