Skip to content

Multi Tenant README

github-actions[bot] edited this page Sep 2, 2026 · 46 revisions

Multi-Tenant Architecture - nself-chat v0.5.0

Overview

nself-chat now supports full multi-tenant SaaS deployment with:

  • Subdomain Routing: tenant1.nchat.app, tenant2.nchat.app
  • Custom Domains: chat.acme.com (optional)
  • Schema-Level Isolation: Each tenant gets isolated PostgreSQL schema
  • Stripe Billing: Integrated subscription management
  • Resource Limits: Per-plan usage enforcement
  • Usage Tracking: Real-time monitoring and analytics

Quick Start

1. Enable Multi-Tenancy

# .env.local
ENABLE_MULTI_TENANCY=true
NEXT_PUBLIC_BASE_DOMAIN=nchat.app

2. Run Migration

cd .backend
nself db migrate up 030_multi_tenant_system.sql

3. Configure Stripe

# .env.local
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

4. Create First Tenant

curl -X POST http://localhost:3000/api/tenants/create \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "slug": "acme",
    "ownerEmail": "admin@acme.com",
    "ownerName": "John Doe",
    "ownerPassword": "securepass123",
    "plan": "free",
    "trial": true
  }'

5. Access Tenant

Visit: http://acme.localhost:3000 (development)

Or: https://acme.nchat.app (production)

Architecture

Database Structure

public (global)
β”œβ”€β”€ tenants              β†’ Tenant metadata
β”œβ”€β”€ tenant_usage         β†’ Usage statistics
β”œβ”€β”€ tenant_settings      β†’ Configuration
β”œβ”€β”€ tenant_invitations   β†’ Invite system
β”œβ”€β”€ tenant_audit_logs    β†’ Audit trail
└── stripe_webhooks      β†’ Billing events

tenant_acme (isolated)
β”œβ”€β”€ nchat_users          β†’ Acme's users
β”œβ”€β”€ nchat_channels       β†’ Acme's channels
β”œβ”€β”€ nchat_messages       β†’ Acme's messages
└── ...                  β†’ All chat tables

tenant_demo (isolated)
β”œβ”€β”€ nchat_users
β”œβ”€β”€ nchat_channels
└── ...

Request Flow

1. User β†’ acme.nchat.app
2. Middleware β†’ Extract subdomain "acme"
3. Database β†’ Fetch tenant metadata
4. Context β†’ Set X-Tenant-Id, X-Tenant-Schema
5. Queries β†’ All scoped to tenant_acme schema
6. Response β†’ Tenant-branded UI

Key Components

1. Tenant Service (src/lib/tenants/tenant-service.ts)

Core service for tenant CRUD operations:

import { getTenantService } from '@/lib/tenants/tenant-service'

const service = getTenantService()

// Create tenant
const tenant = await service.createTenant({
  name: 'Acme Corp',
  slug: 'acme',
  ownerEmail: 'admin@acme.com',
  // ...
})

// Get tenant
const tenant = await service.getTenantBySlug('acme')

// Update tenant
await service.updateTenant(tenant.id, {
  name: 'Acme Corporation',
})

// Delete tenant
await service.deleteTenant(tenant.id)

2. Billing Service (src/lib/billing/stripe-service.ts)

Stripe integration for subscriptions:

import { getStripeBillingService } from '@/lib/billing/stripe-service'

const billing = getStripeBillingService()

// Create checkout session
const session = await billing.createCheckoutSession(tenant, 'pro', 'monthly', successUrl, cancelUrl)

// Manage subscription
await billing.updateSubscription(tenant, 'enterprise', 'yearly')
await billing.cancelSubscription(tenant)

3. Tenant Middleware (src/lib/tenants/tenant-middleware.ts)

Resolves tenant from domain:

// Automatic tenant resolution in middleware
export async function middleware(request: NextRequest) {
  const config = getDefaultTenantConfig()
  const response = await tenantMiddleware(request, config)
  return response
}

4. Tenant Context (src/contexts/tenant-context.tsx)

React context for tenant data:

import { useTenant, useTenantFeature } from '@/contexts/tenant-context'

function MyComponent() {
  const { tenant, isLoading } = useTenant()
  const hasVideoCalls = useTenantFeature('videoCalls')

  return (
    <div>
      <h1>{tenant?.name}</h1>
      {hasVideoCalls && <VideoCallButton />}
    </div>
  )
}

Subscription Plans

Free Plan

  • 10 users
  • 5 channels
  • 1 GB storage
  • 1,000 API calls/month
  • Basic features only

Pro Plan ($15/month or $150/year)

  • 100 users
  • 50 channels
  • 100 GB storage
  • 50,000 API calls/month
  • All features + analytics

Enterprise Plan ($99/month or $990/year)

  • Unlimited users
  • Unlimited channels
  • Unlimited storage
  • Unlimited API calls
  • All features + SSO + priority support

Custom Plan (Contact Sales)

  • Custom limits
  • Custom features
  • Dedicated support
  • SLA guarantees

API Routes

Tenant Management

  • POST /api/tenants/create - Create new tenant
  • GET /api/tenants/[id] - Get tenant
  • PUT /api/tenants/[id] - Update tenant
  • DELETE /api/tenants/[id] - Delete tenant
  • GET /api/tenants/by-slug?slug=acme - Get by subdomain
  • GET /api/tenants/by-domain?domain=chat.acme.com - Get by custom domain

Billing

  • POST /api/billing/checkout - Create Stripe checkout
  • POST /api/billing/portal - Access billing portal
  • POST /api/billing/webhook - Stripe webhook endpoint

Environment Variables

See .env.multi-tenant.example for complete configuration.

Critical Variables:

# Multi-tenancy
ENABLE_MULTI_TENANCY=true
NEXT_PUBLIC_BASE_DOMAIN=nchat.app

# Stripe
STRIPE_SECRET_KEY=sk_...
STRIPE_WEBHOOK_SECRET=whsec_...

# Database
DATABASE_URL=postgresql://...

Deployment

Production Checklist

  • Wildcard DNS configured (*.nchat.app)
  • Wildcard SSL certificate installed
  • Stripe webhook endpoint configured
  • Database migration run
  • Redis cache configured
  • Environment variables set
  • Rate limiting enabled
  • Backups automated

Docker Deployment

docker build -t nchat-multi:latest .
docker run -d \
  --name nchat \
  -p 3000:3000 \
  --env-file .env.production \
  nchat-multi:latest

Vercel Deployment

vercel --prod
vercel env add ENABLE_MULTI_TENANCY production
vercel env add STRIPE_SECRET_KEY production

Security

Row-Level Security (RLS)

All tenant data protected by PostgreSQL RLS:

-- Only super admins can see all tenants
CREATE POLICY tenants_super_admin_all ON public.tenants
  USING (
    EXISTS (
      SELECT 1 FROM auth.users
      WHERE auth.users.id = auth.uid()
      AND auth.users.raw_app_meta_data->>'role' = 'super_admin'
    )
  );

-- Tenant owners can see their own tenant
CREATE POLICY tenants_owner_select ON public.tenants
  FOR SELECT
  USING (owner_id = auth.uid());

Tenant Isolation

  • Each tenant schema completely isolated
  • Middleware enforces schema scoping
  • No shared tables between tenants
  • Cross-tenant queries impossible

Rate Limiting

Per-tenant rate limits based on plan:

  • Free: 60 requests/minute
  • Pro: 120 requests/minute
  • Enterprise: 300 requests/minute

Monitoring

Usage Tracking

-- Current month usage
SELECT * FROM public.tenant_usage
WHERE tenant_id = '{id}' AND period = '2026-01';

Audit Logs

-- Tenant actions
SELECT * FROM public.tenant_audit_logs
WHERE tenant_id = '{id}'
ORDER BY created_at DESC;

Health Checks

# Application health
curl https://nchat.app/api/health

# Tenant health
curl https://acme.nchat.app/api/health

Troubleshooting

Common Issues

  1. Tenant Not Found

    • Check DNS propagation
    • Verify tenant exists in database
    • Check middleware logs
  2. Stripe Webhook Failing

    • Verify webhook secret
    • Check Stripe Dashboard events
    • Review webhook logs table
  3. Cross-Tenant Data Leak

    • CRITICAL: Suspend all tenants
    • Review RLS policies
    • Audit recent queries

Migration Path

From Single-Tenant to Multi-Tenant

-- 1. Create default tenant for existing data
INSERT INTO public.tenants (
  name, slug, status, owner_email, owner_name,
  schema_name, billing_plan
) VALUES (
  'Default Organization',
  'default',
  'active',
  'owner@example.com',
  'Owner',
  'nchat',  -- Point to existing nchat schema
  'enterprise'
);

-- 2. Enable multi-tenancy
-- .env.local
ENABLE_MULTI_TENANCY=true
DISABLE_MULTI_TENANCY=false
DEFAULT_TENANT_SLUG=default

Support


Version: 0.5.0 Last Updated: January 30, 2026 Status: Production Ready


🎯 Getting Started


✨ Features

Core Features

Communication

Security & Privacy

(See πŸ” Security section below for 2FA, PIN Lock, and security audits.)

Interactive

(Search lives in πŸ“š Reference below.)

Extensibility


πŸ“– Guides

User Guides

Developer Guides

Enterprise

Backend

Deployment


βš™οΈ Configuration


πŸ“‘ API

API Documentation


πŸš€ Deployment


πŸ“š Reference

Architecture

Quick Reference


πŸ” Security


πŸ†˜ Help


ℹ️ About


πŸ”— Links


v1.0.0 β€’ 2026

Clone this wiki locally