Guidance Required for Configuring Multi-Zone, Multi-Tenant Next.js App #80482
Replies: 1 comment
-
Great question! This is a sophisticated architecture challenge. Here's a practical approach based on Next.js docs and real-world patterns: The Core ChallengeYou're right that Recommended Architecture1. Middleware-Based Dynamic Routing (Primary Solution)Use middleware for runtime tenant resolution: // middleware.js
import { NextResponse } from 'next/server'
export async function middleware(request) {
const { hostname, pathname } = request.nextUrl
// Skip internal Next.js routes
if (pathname.startsWith('/_next') || pathname.startsWith('/api/internal')) {
return NextResponse.next()
}
// Extract subdomain zone (auth.domain.com -> auth)
const subdomain = hostname.split('.')?.[0]
// For tenant domains (client1.com), resolve tenant context
const tenantDomain = await resolveTenantDomain(hostname)
if (tenantDomain?.tenantId) {
// Rewrite to tenant-specific path
const url = request.nextUrl.clone()
url.pathname = `/tenant/${tenantDomain.tenantId}${pathname}`
// Add tenant context headers
const response = NextResponse.rewrite(url)
response.headers.set('x-tenant-id', tenantDomain.tenantId)
response.headers.set('x-zone', subdomain)
return response
}
return NextResponse.next()
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)']
} 2. Zone Configuration StrategyFor multi-zone with AWS Amplify, use environment-based configuration: // next.config.js
module.exports = {
async rewrites() {
const zoneRewrites = []
// Base zone routing - static at build time
const zones = {
auth: process.env.AUTH_ZONE_DOMAIN,
dashboard: process.env.DASHBOARD_ZONE_DOMAIN,
api: process.env.API_ZONE_DOMAIN
}
Object.entries(zones).forEach(([zone, domain]) => {
if (domain) {
zoneRewrites.push({
source: `/${zone}/:path*`,
destination: `${domain}/${zone}/:path*`
})
// Handle static assets for each zone
zoneRewrites.push({
source: `/${zone}-static/:path*`,
destination: `${domain}/_next/:path*`
})
}
})
return zoneRewrites
},
// Enable basePath for zone-specific deployments
basePath: process.env.ZONE_BASE_PATH || ''
} 3. Tenant API Integration PatternCache tenant data to avoid API calls on every request: // lib/tenant-resolver.js
const tenantCache = new Map()
const CACHE_TTL = 5 * 60 * 1000 // 5 minutes
export async function resolveTenantDomain(hostname) {
const cached = tenantCache.get(hostname)
if (cached && (Date.now() - cached.timestamp) < CACHE_TTL) {
return cached.data
}
try {
const response = await fetch(`${process.env.TENANT_API_URL}/resolve`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ domain: hostname })
})
const tenantData = await response.json()
// Cache the result
tenantCache.set(hostname, {
data: tenantData,
timestamp: Date.now()
})
return tenantData
} catch (error) {
console.error('Tenant resolution failed:', error)
return null
}
} AWS Amplify Specific SolutionsIssue: Amplify + Multi-Zone CoordinationSolution: Deploy zones independently but coordinate through:
# In each Amplify app
ZONE_TYPE=auth # or dashboard, api
MAIN_DOMAIN=domain.com
TENANT_API_URL=https://api.domain.com
# amplify.yml
version: 1
frontend:
phases:
preBuild:
commands:
- npm ci
- npm run validate-zone-config
build:
commands:
- npm run build
- npm run post-build-zone-sync Alternative: CloudFront + ALB PatternFor more control than Amplify allows: // CloudFront Origin Groups
const origins = {
auth: 'auth.amplify-domain.com',
dashboard: 'dashboard.amplify-domain.com',
api: 'api.amplify-domain.com'
}
// Route based on path patterns
const behaviors = [
{ pathPattern: '/auth/*', targetOrigin: 'auth' },
{ pathPattern: '/dashboard/*', targetOrigin: 'dashboard' },
{ pathPattern: '/api/*', targetOrigin: 'api' }
] Performance Optimizations
Tested Patterns from Next.js CodebaseBased on the official examples: This architecture scales well and maintains the benefits of both multi-zone isolation and dynamic tenant routing. Would you like me to elaborate on any specific part of this setup? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
We are currently developing a multi-tenant application using Next.js with a multi-zone microfrontend architecture. Each zone is deployed as a separate repository to an individual AWS Amplify app, all within the same cloud environment.
Here is our setup:
We are using a shared cloud environment (AWS Amplify) where each zone is deployed under a unique subdomain (e.g., auth.domain.com, dashboard.domain.com), while maintaining the same base domain.
Our application retrieves tenant-specific details at runtime through a Tenant API.
Each tenant is served through a different custom domain (e.g., client1.com, client2.com) that maps to the same set of zones.
Our routing needs to adapt dynamically to both the zone (subdomain) and the tenant domain.
Challenge:
The next.config.js (or .ts) file requires zone domain configuration at build time, but in our case, the actual tenant domain mappings are only available at runtime via API. Since we are using the same Amplify environment for all tenants and dynamically route based on domain and tenant context, it becomes difficult to statically define all possible routes or zone domains in the configuration file ahead of time.
Request:
Could you please help us with the recommended approach to configure and manage routes for a multi-tenant, multi-zone setup in Next.js under these conditions?
Specifically, we’re looking for best practices on:
Your guidance on how to proceed with this dynamic multi-tenant setup within the Next.js multi-zone structure would be greatly appreciated.
Additional information
No response
Example
No response
Beta Was this translation helpful? Give feedback.
All reactions