Provides architecture guidance for multi-tenant SaaS platforms on Cloudflare or Vercel. Use when defining domain strategy, tenant identification, isolation, subdomain routing, custom domains, white-label setup, tenant separation, plan/limit mapping, building a multi-tenant application, or asking "how do I support multiple tenants" or "build a white-label platform".
Provides architecture guidance for multi-tenant SaaS platforms on Cloudflare or Vercel. Use when defining domain strategy, tenant identification, isolation, subdomain routing, custom domains, white-label setup, tenant separation, plan/limit mapping, building a multi-tenant application, or asking "how do I support multiple tenants" or "build a white-label platform".
Cloudflare: Workers for Platforms + dispatch namespaces for per-tenant code isolation; best when tenants run untrusted code or you need edge-first compute with D1/KV/DO primitives.
Vercel: Next.js App Router + Middleware for shared-app multi-tenancy; best when tenants share one codebase and you need ISR, React Server Components, and managed deployment.
Pick one; do not mix hosting. The remaining steps apply to both with platform-specific guidance in reference files.
After choosing, load only the references for that platform unless you are explicitly comparing Cloudflare vs Vercel.
Choose domain strategy
Use a dedicated tenant domain (separate from the brand domain) for all subdomains/custom hostnames. Reputation does not isolate; a phishing site on random.acme.com damages the whole domain.
Register a separate TLD for tenant workloads (e.g. acme.app for tenants, acme.com for brand).
Consider PSL for browser cookie isolation; it does not protect reputation. See psl.md.
Start PSL submission early; review can take weeks.
Choose tenant identification strategy
Subdomain-based: tenant.yourdomain.com. Requires wildcard DNS. Simplest for many tenants.
Custom domain: Tenant brings own domain, CNAMEs to your platform. Best for serious/paying tenants.
Path-based: yourdomain.com/tenant-slug. No DNS/SSL per tenant, but limits branding and complicates cookie isolation.
Pick one primary strategy; offer custom domain as an upgrade path.
Define isolation model
Cloudflare: Prefer per-tenant Workers for untrusted code (Workers for Platforms dispatch namespaces). Avoid shared-tenant branching unless you fully control code and data.
Vercel: Single shared Next.js app with tenant_id scoping. Middleware resolves tenant from hostname; all data queries include tenant context. Use Postgres RLS for defence-in-depth.
Route traffic deterministically
Cloudflare: Platform Worker owns routing; hostname -> tenant id -> dispatch namespace -> tenant Worker. 404 when no mapping exists.
Vercel: Next.js Middleware extracts hostname, rewrites URL to /domains/[domain] dynamic segment. Edge Config for sub-millisecond tenant lookups. 404 when no mapping exists.
Tenants never control routing or see each other on either platform.
Pass tenant context through the stack
Cloudflare: Platform Worker resolves tenant and injects headers or bindings before dispatching to tenant Worker.
Vercel: Middleware sets x-tenant-id, x-tenant-slug, x-tenant-plan on forwarded request headers. Server Components read via headers(); API routes read from request headers:
Middleware/platform Worker is the single authority; never trust client-supplied tenant identity.
Bind only what is needed
Cloudflare: Least-privilege bindings per tenant (DB/storage/limited platform API), no shared global state. Treat new bindings as explicit changes; redeploy to grant access.
Vercel: Edge Config for tenant config (domain mappings, feature flags, plan info). Vercel SDK (@vercel/sdk) for domain management. Database connection scoped by tenant_id or database-per-tenant (Neon).
Support custom domains
Provide DNS target, verify ownership, store mapping, and route by hostname.
Cloudflare: Cloudflare for SaaS custom hostnames + managed certs. See cloudflare-platform.md.
Vercel: Vercel Domains API via @vercel/sdk for programmatic domain CRUD + automatic Let's Encrypt SSL. Wildcard subdomains require Vercel nameservers. See vercel-domains.md.
Custom domains shift reputation to the tenant and create natural user segments (casual on platform domain, serious on own domain).
Serve per-tenant static files
robots.txt, sitemap.xml, llms.txt must vary by tenant; do not serve from /public.
Cloudflare: Generate per-tenant responses in the tenant Worker.
Re-check limits in official docs before final architecture or pricing decisions.
Make the API the product
Everything works over HTTP; UI is for ops/incident/billing.
Platform logic stays in the routing layer (dispatch Worker or Middleware); tenant content serves requests.
If it only works in the UI, the platform is leaking.
Extend without breaking boundaries
Add queues/workflows/containers as optional modes.
Keep routing explicit and isolation intact.
Gotchas
Don't use the brand domain for tenant subdomains — a phishing site on random.acme.com damages the entire acme.com reputation. Use a separate TLD for tenant workloads.
Don't skip PSL submission — review takes weeks, not days. Start early or your cookie isolation timeline slips.
Don't trust client-supplied tenant identity even behind auth — middleware/platform Worker is the single authority for tenant resolution.
Don't mix hosting platforms — pick Cloudflare or Vercel and commit. Hybrid setups create routing complexity that compounds.
Don't start with path-based tenancy if custom domains are on the roadmap — migrating from path-based to subdomain/custom-domain later requires URL rewrites, cookie changes, and DNS migration.
Don't share database connections across tenants without RLS or tenant_id scoping — a missing WHERE clause leaks data.
Deliverables
Platform choice rationale: Cloudflare vs Vercel with justification
Tenant identification strategy: subdomain, custom domain, or path-based