Multi-Tenancy for NestJS SaaS — Schema-Per-Tenant with TypeORM
There are three approaches to multi-tenancy: shared database with row-level filtering, schema-per-tenant, and database-per-tenant. Shared databases leak data when a developer forgets a WHERE clause. Separate databases cost a fortune at scale. Schema-per-tenant gives you true isolation with a single database connection — the best balance of security, cost, and operational simplicity.
The Cloudrix SaaS Starter Kit implements schema-per-tenant isolation with TypeORM and PostgreSQL. Every request is scoped to the current tenant via middleware, so queries never cross tenant boundaries. Organizations, roles, team invitations, and member management are all built in — you just add your business logic on top.
Organizations
Create and manage multiple organizations. Each org has its own members, settings, and data. Users can belong to multiple organizations and switch between them seamlessly from the dashboard.
RBAC with 4 Roles
Owner, Admin, Member, and Viewer roles with granular permission checks on every endpoint. Roles are enforced via NestJS guards and decorators, making it impossible to bypass authorization even if the frontend is compromised.
Tenant Isolation
Schema-level isolation ensures tenants never see each other's data. Every query is automatically scoped to the current tenant's schema via middleware. No WHERE clause to forget — isolation is structural, not conditional.
Team Invitations
Invite members by email with role assignment. Pending invites with expiry and resend support. Invited users who don't have an account yet are prompted to register, then automatically join the organization with the assigned role.
Org Switching
Seamlessly switch between organizations from the dashboard. Context preserved per org. The active organization is stored in the JWT token and validated on every request, so there's no state confusion between tenants.
Permission Matrix
Visual permission matrix showing which roles can access which features and endpoints. Easily extendable — add a new permission by adding a single entry to the matrix. The UI auto-generates from the backend permission config.
How It Works in Code
Tenant context is resolved from the JWT token and injected into every request. All queries are automatically scoped to the current tenant:
// Middleware sets the tenant schema on every request
@Injectable()
export class TenantMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
const tenantId = req.user?.organizationId;
if (tenantId) {
req['tenantSchema'] = 'tenant_' + tenantId;
}
next();
}
}
// Queries are automatically scoped — no WHERE clause needed
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(Role.ADMIN, Role.OWNER)
@Get('members')
getMembers(@TenantConnection() repo: Repository<Member>) {
return repo.find(); // Only returns current tenant's members
}What's Included
Explore More Features
One-time purchase. 14-day money-back guarantee.