Skip to content

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

Schema-per-tenant isolation
Automatic tenant provisioning
Tenant context middleware
Organization management
Team invitations with email
Member roles (Owner, Admin, Member, Viewer)
Data isolation guarantees
Tenant-aware queries via TypeORM
Cross-tenant admin access
Migration per schema
Get SaaS Starter Pro — $249

One-time purchase. 14-day money-back guarantee.