Multi-Tenant Architecture

Build a B2B SaaS application with complete tenant isolation using subdomains.

Architecture Overview

Tenant A (company-a.yourapp.com)
  ├── Organization 1 (Engineering Team)
  ├── Organization 2 (Marketing Team)
  └── Users (isolated data)

Tenant B (company-b.yourapp.com)
  ├── Organization 1 (Sales Team)
  └── Users (isolated data)

Each tenant gets their own subdomain with completely isolated data, users, and organizations.

Key Features

🔒 Complete Data Isolation

Each tenant's data is completely separated at the database level

🌐 Subdomain Routing

company-a.yourapp.com and company-b.yourapp.com

⚙️ Per-Tenant Configuration

Each tenant can have different security settings and branding

👥 Organization Support

Multiple organizations within each tenant

Step 1: Set Up Tenant Middleware

Extract subdomain from the request and add it to headers:

middleware.ts

Step 2: Create Tenant Resolver

Helper functions to get the current tenant from subdomain:

lib/tenant.ts

Step 3: Make Auth Tenant-Aware

Customize NextAuth to verify users belong to the current tenant:

app/api/auth/[...nextauth]/route.ts

Step 4: Create Tenant Dashboard

Display tenant-specific data and verify access:

app/dashboard/page.tsx

Step 5: Tenant Creation API

Allow new tenants to sign up with their own subdomain:

app/api/tenants/route.ts

DNS Configuration

DNS Setup

Data Isolation Best Practices

✅ Always Filter by tenantId

Every database query should include tenantId filter:

where: { tenantId: tenant.id }

✅ Use Prisma Middleware

Automatically add tenantId filter to all queries to prevent data leaks

✅ Verify Tenant Access in APIs

Always verify the current user belongs to the tenant they're trying to access

❌ Never Trust Client-Side tenantId

Always derive tenantId from subdomain/session, never from request body

Testing Multi-Tenant Locally

1. Edit /etc/hosts

Add local subdomain mappings:

127.0.0.1 company-a.localhost
127.0.0.1 company-b.localhost

2. Access via Subdomain

Visit http://company-a.localhost:3000

3. Verify Isolation

Try to access another tenant's data - should be blocked

Production Considerations

🚀 Performance

  • • Cache tenant data by subdomain
  • • Use connection pooling
  • • Index tenantId on all tables

🔒 Security

  • • SSL certificates for all subdomains
  • • Rate limiting per tenant
  • • Audit logs for cross-tenant access attempts

📊 Monitoring

  • • Track usage per tenant
  • • Alert on data isolation violations
  • • Monitor database query patterns

💰 Billing

  • • Track usage per tenant
  • • Implement usage-based pricing
  • • Handle plan upgrades/downgrades

Next Steps