- Next.js
- Enterprise Architecture & System Design
- Multi-Tenant Architecture & Custom Subdomain Routing
Multi-Tenant Architecture & Custom Subdomain Routing
Multi-tenant Next.js platforms (like Shopify or Notion sites) serve thousands of custom domains and subdomains from a single deployment. Requests are intercepted at the network layer via proxy.ts/middleware.ts, extracting the host header and internally rewriting requests to tenant-specific dynamic segments (app/[tenant]/...) while preserving the custom domain in the browser address bar.
Learning Objectives
Architect single-codebase multi-tenant SaaS platforms serving custom subdomains.
Implement URL rewrites based on incoming Host headers.
Enforce database multi-tenant data isolation at the ORM layer.
Configure wildcard DNS and SSL termination for custom customer domains.
Prerequisites & Background Knowledge
Why Interviewers Care
Flagship enterprise system design question. Tests ability to scale a single Next.js codebase across B2B SaaS tenants.
The Challenge
Design a multi-tenant platform in Next.js that routes tenant subdomains (e.g. acme.platform.com) and custom domains (e.g. store.acme.com) to dynamic tenant route segments without changing the user address bar.
Code Architecture & Implementation
1// middleware.ts or proxy.ts2import { NextRequest, NextResponse } from 'next/server';34export const config = {5 matcher: ['/((?!api/|_next/|_static/|[\\w-]+\\.\\w+).*)'],6};78export function middleware(req: NextRequest) {9 const url = req.nextUrl;10 const hostname = req.headers.get('host') || '';1112 // Standard root domain13 const rootDomain = process.env.NEXT_PUBLIC_ROOT_DOMAIN || 'platform.com';1415 let currentHost: string;16 if (hostname.includes(rootDomain)) {17 // Extract subdomain: 'acme.platform.com' -> 'acme'18 currentHost = hostname.replace(`.${rootDomain}`, '');19 } else {20 // Custom domain: 'store.customer.com'21 currentHost = hostname;22 }2324 // Handle root landing page25 if (currentHost === rootDomain || currentHost === 'www' || currentHost === '') {26 return NextResponse.rewrite(new URL('/home', req.url));27 }2829 // Rewrite internally to the tenant folder:30 // Browser stays at https://acme.platform.com/products31 // Next.js serves app/[tenant]/products/page.tsx32 return NextResponse.rewrite(33 new URL(`/${currentHost}${url.pathname}${url.search}`, req.url)34 );35}
Architectural Explanation
Rather than deploying separate servers for each customer, multi-tenant architecture uses DNS wildcards (*.platform.com). Incoming requests arrive at the Next.js edge/proxy with the customer domain in the Host header. The proxy inspects the host, identifies the tenant slug, and rewrites the request internally to /[tenant]/.... The underlying database queries strictly filter by tenant_id, guaranteeing complete data isolation between customers within a single scalable deployment.
Common Mistakes & Anti-Patterns
Using `NextResponse.redirect()` instead of `NextResponse.rewrite()`, which exposes internal `/tenant/...` URLs in the browser address bar.
Failing to isolate database queries by tenant ID, leading to critical cross-tenant data leaks.
Not caching tenant domain lookups, causing duplicate database queries on every single asset request.
Interview Follow-Up Traps
The interviewer asks: "How do you handle custom domains (e.g. acme.com) instead of subdomains?" You configure customers to set a CNAME pointing to your domain, and your proxy looks up the custom domain in your database to find the tenant ID.
Frequently Asked Questions
Can tenants have their own generateStaticParams?
Yes! You can pre-generate top customer subdomains at build time or generate them on-demand via ISR.
Does multi-tenancy work with Server Actions?
Yes! Ensure your allowedOrigins in next.config.js includes `*.yourdomain.com`.
