Multi-Tenant Platform Concepts
Multi-Tenant Platform Concepts
Tenants
What is a tenant
A tenant represents a customer, workspace, or organization within your multi-tenant application. Each tenant has its own data, configuration, and branding, but all tenants share the same codebase and deployment.
Examples:
- Blog platform: Each writer with their own blog is a tenant
- Documentation platform: Each company with its own docs site is a tenant
- E-commerce platform: Each store owner is a tenant
Tenant identification strategies
You can identify tenants using three approaches:
- Subdomain-based: Extract the tenant from the subdomain (
tenant1.yourapp.com)
const hostname = request.headers.get('host');
const subdomain = hostname.split('.')[0]; // "tenant1"
- Custom domain-based: Map custom domains to tenants (
tenant1.com→ Tenant 1)
// Map custom domain to tenant in database
const tenant = await db.tenant.findFirst({
where: { customDomain: hostname },
});
- Path-based: Extract tenant from URL path (
/tenant1/dashboard)
const pathname = request.nextUrl.pathname;
const tenantSlug = pathname.split('/')[1]; // "tenant1"
Tenant data isolation
Multi-tenant applications must isolate data between tenants:
- Database-level: Use tenant ID in all queries
database.ts
const posts = await db.post.findMany({
where: { tenantId: tenant.id },
});
- Application-level: Next.js Proxy ensures requests can only access their tenant's data
- Global Config: Store tenant configuration for fast lookups at the edge
Domains
Wildcard domains
Wildcard domains let you automatically serve all subdomains from a single Vercel project:
- Add
*.yourapp.comto your project - Point your domain to Vercel's nameservers
- Any subdomain (
tenant1.yourapp.com,tenant2.yourapp.com) automatically routes to your app - Vercel issues SSL certificates for each subdomain on the fly
Requirements: Must use Vercel's nameservers (ns1.vercel-dns.com, ns2.vercel-dns.com)
Custom domains
Custom domains let tenants bring their own domain:
- Add
tenant1.comto your Vercel project via SDK - Tenant configures DNS (CNAME or nameservers)
- Verify domain ownership (TXT record)
- Vercel issues SSL certificate automatically
SSL certificate issuance
Vercel automatically issues SSL certificates for all domains using Let's Encrypt:
- Wildcard domains: Single wildcard certificate covers all subdomains
- Custom domains: Individual certificate per domain
- Automatic renewal before expiration
- No configuration required
Domain verification
For domains already in use on Vercel, ownership verification is required:
- Add domain to your project
- Vercel generates a unique TXT record
- Tenant adds TXT record to their DNS
- Verify ownership via SDK or dashboard
- Certificate issues once verified
Routing
How Proxy resolves tenants
Next.js Proxy runs on every request before your pages render:
export async function proxy(request: NextRequest) {
const hostname = request.headers.get('host');
// Get tenant from subdomain or custom domain
const tenant = await resolveTenant(hostname);
// Forward tenant context to your app on the request headers
const requestHeaders = new Headers(request.headers);
requestHeaders.set('x-tenant-id', tenant.id);
return NextResponse.next({
request: { headers: requestHeaders },
});
}
Request handling flow
- User visits
tenant1.yourapp.com - Request hits Vercel's CDN
- Proxy extracts subdomain (
tenant1) - Proxy looks up tenant in database or Global Config
- Proxy adds tenant context to the request headers
- Page component reads tenant from headers
- Page renders with tenant-specific data
Performance considerations
- Global Config: Store tenant configuration at the edge for sub-10ms lookups
import { get } from '@vercel/global-config';
const tenant = await get(`tenant_${hostname}`);
- Caching: Cache tenant lookups in the proxy to reduce database queries
- Connection pooling: Use connection pooling for database queries to handle multiple tenants efficiently
Architecture
Single deployment serving multiple domains
Multi-tenant architecture means:
- One Next.js codebase
- One Vercel deployment
- Multiple domains (subdomains + custom domains)
- Shared infrastructure and resources
- Tenant-aware routing and data access
Tenant context
Pass tenant information through your application:
- In Proxy: Forward context on the request headers
const requestHeaders = new Headers(request.headers);
requestHeaders.set('x-tenant-id', tenant.id);
return NextResponse.next({
request: { headers: requestHeaders },
});
- In server components: Read headers
import { headers } from 'next/headers';
const headersList = await headers();
const tenantId = headersList.get('x-tenant-id');
- In API routes: Access request headers
const tenantId = request.headers.get('x-tenant-id');
Last updated August 20, 2026