Every time you build a SaaS product, you hit the same wall: spending the first few days re-writing multi-tenant architecture, handling tenant context isolation, setting up JWT guards, and building permission directives.
After open-sourcing the initial Unified Role-Based Access Control boilerplate, the most common question I thought about was: “How to scale this for multi-tenancy?”
Building multi-tenant apps means dealing with a cascade of complexities: tenant context resolution, isolated access control policies, routing adjustments, and clean database partitioning. Building all of that from scratch for every B2B SaaS project is a massive time sink.
So I built a production-ready solution once, engineered it cleanly, and open-sourced it: MT-URBAC (Multi-Tenant Unified Role-Based Access Control).
What is MT-URBAC?
MT-URBAC is a full-stack, enterprise-grade boilerplate designed to let you spin up a secure, multi-tenant B2B application in under five minutes.
- Backend: NestJS, TypeORM, PostgreSQL
- Frontend: Angular, OptimusUI, Tailwind CSS
- License: 100% Free & Open-Source (MIT)
Key Architectural Breakthroughs
1. Zero-Hassle Local Multi-Tenant Routing
Testing subdomains locally usually requires hacking your OS /etc/hosts file and running custom proxy configurations. MT-URBAC solves this out of the box with dual-mode routing:
- Local Development (Path-Based): Zero setup required. Test tenant boundaries instantly using clean paths like http://localhost:4200/tenant-a/login or http://localhost:4200/admin/....
- Production (Subdomain-Based): Automatically maps incoming host headers (tenant-a.yourdomain.com) to tenant contexts seamless in production.
2. Clean Top-Down Grouping (No Junction-Table Hell)
Instead of messy three-way many-to-many junction tables that destroy query performance, MT-URBAC enforces a streamlined hierarchy:
User → Group → Role → Privilege
3. Automatic Privilege Escalation Defense
Security flaw #1 in custom RBAC systems is horizontal/vertical privilege escalation (e.g., an Admin granting someone Super Admin privileges). MT-URBAC assigns numeric weight levels to every role (e.g., Admin = 50, Super Admin = 100). The NestJS guards intercept and reject any action where a user attempts to mutate or assign a role higher than their own level.
Developer Experience (DX) First
Protecting backend endpoints takes a single line:
@Post('create')
@RequirePermissions('user:create')
async createNewUser() {
// Executed only if the user possesses 'user:create' in their active tenant context
}
Hiding or rendering elements dynamically in Angular requires zero boilerplate logic in your components:
<!-- Automatically listens to user permission state -->
<button *hasPermission="'user:delete'" class="p-button-danger">
Delete User
</button>
Try It in 2 Minutes
# 1. Clone & install
git clone https://github.com/kasoir/mt-urbac.git
cd mt-urbac/backend && npm install
# 2. Seed database & start
npm run seed
npm run start:dev
The repository ships with an automated database seeder that provisions default roles, privileges, and a Super Admin account out of the box (admin@mt-urbac.com / Admin123!).
Check out the source code on GitHub: https://github.com/kasoir/mt-urbac
If this saves you a weekend of architecture setup, drop a Star on the repo! I'd love to hear in the comments how you typically handle multi-tenancy isolation in your projects.
Top comments (0)