js

Build Multi-Tenant SaaS with NestJS, Prisma & Row-Level Security - Complete Developer Guide

Learn to build scalable multi-tenant SaaS apps with NestJS, Prisma & PostgreSQL Row-Level Security. Complete guide with authentication, performance tips & best practices.

Build Multi-Tenant SaaS with NestJS, Prisma & Row-Level Security - Complete Developer Guide

Recently, I was working on a new SaaS project and realized how crucial it is to build a system that can securely serve multiple customers without mixing their data. This led me to explore combining NestJS, Prisma, and PostgreSQL’s Row-Level Security for a robust multi-tenant architecture. If you’re building a SaaS application, this approach can save you from reinventing the wheel while ensuring data isolation and scalability.

Multi-tenancy means a single application serves multiple clients, keeping their data separate. I prefer the shared schema method with Row-Level Security because it balances cost and performance. Did you know that without proper isolation, a simple query could expose one tenant’s data to another? That’s why RLS is a game-changer—it enforces security at the database level.

Setting up the project starts with initializing NestJS and Prisma. I use a structured folder layout to keep things organized. Here’s a quick setup:

npx @nestjs/cli new saas-app --skip-git
npx prisma init
npm install @prisma/client @nestjs/jwt passport-jwt bcryptjs

For the database, PostgreSQL with RLS is key. In your Prisma schema, define models with tenant IDs. Then, enable RLS and create policies to restrict access based on the current tenant. This code sets up a basic tenant and user model:

model Tenant {
  id        String   @id @default(cuid())
  name      String
  subdomain String   @unique
  users     User[]
}

model User {
  id       String   @id @default(cuid())
  email    String   @unique
  tenantId String
  tenant   Tenant   @relation(fields: [tenantId], references: [id])
}

After migrating, add RLS policies in SQL:

ALTER TABLE users ENABLE ROW LEVEL SECURITY;
CREATE POLICY user_isolation ON users USING (tenant_id = current_setting('app.tenant_id'));

How do we make Prisma tenant-aware? I extended the Prisma client to handle tenant context. This service sets the tenant ID for each request, ensuring all queries are scoped:

@Injectable()
export class PrismaService extends PrismaClient {
  async setTenant(tenantId: string) {
    await this.$executeRaw`SELECT set_config('app.tenant_id', ${tenantId}, true)`;
  }
}

In NestJS, I use middleware to extract the tenant from the request—say, from a subdomain or JWT token. This middleware calls setTenant before passing control to the route handler. What happens if the tenant isn’t found? I handle that with a guard that returns a 403 error.

Authentication needs to be tenant-specific. I implement a JWT strategy that includes the tenant ID in the token. When a user logs in, I verify they belong to the correct tenant. Here’s a snippet for a tenant guard:

@Injectable()
export class TenantGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const tenantId = request.user.tenantId;
    if (!tenantId) throw new ForbiddenException('Invalid tenant');
    return true;
  }
}

For services, I inject the Prisma service and ensure all database operations use the set tenant context. This way, every query automatically respects RLS. Have you considered how to handle migrations in a multi-tenant setup? I keep it simple by applying schema changes globally, as all tenants share the same structure.

Performance is critical. I use connection pooling and index tenant IDs to speed up queries. Also, caching tenant-specific data can reduce database load. But remember, always test with multiple tenants to catch isolation issues early.

In my experience, this setup scales well for hundreds of tenants. However, if you expect massive growth, consider separating databases later. The key is starting with a solid foundation.

I’d love to hear your thoughts—have you tried similar approaches, or faced challenges with multi-tenancy? Share your experiences in the comments below, and if this guide helped, please like and share it with others who might benefit!

Keywords: multi-tenant SaaS application, NestJS multi-tenancy, Prisma row level security, PostgreSQL RLS tutorial, tenant isolation database, SaaS architecture patterns, NestJS Prisma integration, multi-tenant authentication, scalable SaaS development, tenant-aware middleware



Similar Posts
Blog Image
Complete Guide to Next.js Prisma Integration: Build Type-Safe Full-Stack Apps in 2024

Learn how to integrate Next.js with Prisma ORM for type-safe, full-stack applications. Build modern web apps with seamless database operations and enhanced developer experience.

Blog Image
Build a Distributed Rate Limiter with Redis, Node.js and TypeScript: Complete Tutorial

Learn to build a scalable distributed rate limiter with Redis, Node.js & TypeScript. Master algorithms, clustering, monitoring & production deployment strategies.

Blog Image
Build Real-Time Analytics Dashboard with Node.js Streams ClickHouse and Server-Sent Events Performance Guide

Learn to build a high-performance real-time analytics dashboard using Node.js Streams, ClickHouse, and SSE. Complete tutorial with code examples and optimization tips.

Blog Image
Complete Guide to Integrating Prisma with GraphQL: Build Type-Safe APIs That Scale in 2024

Learn how to integrate Prisma with GraphQL for type-safe, efficient APIs. Build modern web applications with seamless database connectivity and optimized queries.

Blog Image
Event Sourcing with MongoDB Change Streams and Node.js: Complete Implementation Guide

Learn to implement Event Sourcing with MongoDB Change Streams and Node.js. Complete guide covering CQRS patterns, projections, and real-time event handling.

Blog Image
Complete Authentication System with Passport.js, JWT, and Redis Session Management for Node.js

Learn to build a complete authentication system with Passport.js, JWT tokens, and Redis session management. Includes RBAC, rate limiting, and security best practices.