Module A-10·25 min read

Next.js multi-zones for independent team deploys, basePath and reverse proxy wiring, shared auth across zones, multi-tenant subdomain routing with per-tenant database isolation, and assetPrefix for tenant CDN origins.

A-10 — Multi-Zones, Multi-Tenant, and Distributed Architecture

Who this is for: Architects building applications that have outgrown a single Next.js codebase — either because different teams own different parts of the product (multi-zone), or because the same codebase needs to serve multiple customers with isolated data and custom domains (multi-tenant). This module covers the architectural patterns for both.


Multi-Zone Architecture — One Domain, Multiple Apps

A Next.js multi-zone deployment lets you host multiple independent Next.js applications on the same domain. Each application owns a path prefix, and a reverse proxy routes requests to the right app.

The canonical use case: a large organisation where the marketing site (/), the documentation (/docs), and the main application (/app) are maintained by different teams with different release cycles. Rather than forcing them all into one repository and one deployment, each is an independent Next.js app.

text

On Vercel, this is configured through the project settings as a "multi-zone" setup — each project gets a Vercel domain, and a rewrites config in the primary project routes traffic:

ts

Each zone's next.config.ts sets a basePath so internal links resolve correctly:

ts

Multi-Zone Constraints

Multi-zone has real constraints that trip up teams the first time they try it.

Client-side navigation between zones is not possible. The App Router's client-side navigation works within a single Next.js app. A link from the marketing zone to /docs/getting-started causes a full page navigation — the docs zone app boots fresh. There's no shared React tree between zones.

This is actually fine for the canonical use case (marketing → docs → app are all different products) but becomes a problem if you're trying to use multi-zone for micro-frontend architecture where seamless navigation is expected.

Shared layouts require duplication. If you want a consistent header across all zones, each zone must implement it separately. There's no "shared layout" that spans zones. The coordination problem is usually solved with a shared npm package for the header component.

Router Cache doesn't cross zones. Each zone has its own Router Cache. Navigating from the marketing zone to the docs zone clears the Router Cache.


When Multi-Zone Is the Right Choice

Use multi-zone when:

  • Different parts of the site have legitimately different deployment cadences
  • Different teams own different parts and shouldn't share CI/CD pipelines
  • You're migrating from one architecture to another incrementally (old Pages Router app on /legacy, new App Router app on everything else)
  • Bundle size and cold start time are affected by mixing concerns (a marketing site and a data-heavy application have very different dependencies)

Don't use multi-zone for:

  • Micro-frontend architecture where seamless navigation is required
  • Sharing significant state between zones
  • Performance-critical flows that span zone boundaries

Multi-Tenant Architecture — One App, Many Customers

Multi-tenancy is a different problem entirely. One Next.js application serves multiple customers (tenants), each with their own data, potentially their own domain, and sometimes their own branding.

The three flavours of multi-tenancy in Next.js:

Path-based: example.com/team-a/dashboard, example.com/team-b/dashboard Subdomain-based: team-a.example.com, team-b.example.com Custom domain: dashboard.team-a-company.com, portal.team-b.com


Path-Based Multi-Tenancy

The simplest. The tenant identifier is in the URL path, available to Server Components as a route param:

text
tsx

Subdomain-Based Multi-Tenancy with Middleware

Subdomain tenancy requires Middleware to extract the tenant from the hostname and inject it into the request:

ts

This rewrite is invisible — team-a.example.com/dashboard is rewritten to serve content from /team-a/dashboard internally, but the URL in the browser stays as team-a.example.com/dashboard.


Custom Domain Multi-Tenancy

Custom domains — where tenants use their own domain (app.customer.com) pointing to your application — are the most complex variant. The tenant-to-domain mapping must be stored in a database and the Middleware must look it up.

The challenge: Middleware can't use Prisma. The solution is a lightweight, edge-compatible lookup:

ts

The next: { revalidate: 300 } on the lookup fetch is critical — without caching, every request to a custom domain triggers a lookup API call, adding latency and load to your lookup service.

For scale, replace the HTTP lookup with Vercel's Edge Config or Upstash Redis — both are edge-compatible and have sub-millisecond read latency for cached values.


Tenant Data Isolation

Multi-tenancy requires rigorous data isolation. The most common architecture:

Row-level isolation (single database): All tenants share a database. Every table has a tenantId column. All queries are scoped with WHERE tenantId = ?. Prisma makes this manageable with middleware:

ts

Schema isolation (single database, multiple schemas): Each tenant gets a PostgreSQL schema. More isolation, more complexity, harder to query across tenants.

Database isolation (separate databases): Maximum isolation. Most expensive. Used when regulatory requirements mandate tenant data separation (healthcare, finance).

For most SaaS applications, row-level isolation with a Prisma extension is the correct default. It handles 99% of use cases and doesn't require complex database management.


Vercel Edge Config for Tenant Routing

Vercel Edge Config is a key-value store readable at the edge with sub-millisecond latency — purpose-built for the tenant routing problem:

ts

Edge Config is populated by your backend when a new custom domain is added — you write to it via the Edge Config API after verifying the domain. The edge reads it in Middleware with no HTTP round trip.


Where We Go From Here

A-11 goes under the hood of the build system — Turbopack replacing Webpack, SWC replacing Babel, and what these changes mean for build times, bundle analysis, and custom configuration. After the architecture patterns of A-10, A-11 explains the engine that produces the deployable output.


Knowledge Check

When using a Multi-Zone architecture to host multiple independent Next.js applications on the same domain, what is a key limitation regarding navigation between the zones?


In a custom domain multi-tenancy architecture (e.g., app.customer.com), why is it recommended to use an edge-compatible store like Vercel Edge Config or Upstash Redis in Middleware, rather than querying a primary database like PostgreSQL?


What is the most common and generally recommended approach for enforcing tenant data isolation in a standard SaaS application utilizing a single database?

Test your knowledge with more question sets

Sign in to access a wider variety of questions and get notified when new practice sets are added to this module.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.