multi-tenant-platform-architecture
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMulti-Tenant Platform Architecture (Cloudflare · Vercel)
多租户平台架构(Cloudflare · Vercel)
Workflow (order matters)
工作流程(顺序至关重要)
- Choose 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 damages the whole domain.
random.acme.com - Register a separate TLD for tenant workloads (e.g. for tenants,
acme.appfor brand).acme.com - 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: . Requires wildcard DNS. Simplest for many tenants.
tenant.yourdomain.com - Custom domain: Tenant brings own domain, CNAMEs to your platform. Best for serious/paying tenants.
- Path-based: . No DNS/SSL per tenant, but limits branding and complicates cookie isolation.
yourdomain.com/tenant-slug - 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 scoping. Middleware resolves tenant from hostname; all data queries include tenant context. Use Postgres RLS for defence-in-depth.
tenant_id
- 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 dynamic segment. Edge Config for sub-millisecond tenant lookups. 404 when no mapping exists.
/domains/[domain] - 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-slugon forwarded request headers. Server Components read viax-tenant-plan; API routes read from request headers.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 () for domain management. Database connection scoped by
@vercel/sdkor database-per-tenant (Neon).tenant_id
- 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 for programmatic domain CRUD + automatic Let's Encrypt SSL. Wildcard subdomains require Vercel nameservers. See vercel-domains.md.
@vercel/sdk - 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.xmlmust vary by tenant; do not serve fromllms.txt./public - Cloudflare: Generate per-tenant responses in the tenant Worker.
- Vercel: Use route handlers per domain segment. See vercel-platform.md.
- Surface limits as plans
- Map platform limits to pricing tiers; expose in API + UI.
- Do not run long jobs in requests; use queues/workflows.
- See limits-and-quotas.md for limits snapshots and source links.
- 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.
- 选择平台
- Cloudflare:使用Workers for Platforms + 调度命名空间实现租户级代码隔离;最适合租户运行不可信代码,或需要基于D1/KV/DO原语的边缘优先计算场景。
- Vercel:采用Next.js App Router + Middleware实现共享应用多租户模式;最适合租户共享单一代码库,且需要ISR、React Server Components和托管部署的场景。
- 二选一;不要混合托管。后续步骤适用于两者,参考文件中会提供平台特定的指导。
- 选择后,仅加载对应平台的参考内容,除非你明确要对比Cloudflare与Vercel。
- 选择域名策略
- 为所有子域名/自定义主机名使用独立的租户域名(与品牌域名分离)。域名信誉无法隔离;上的钓鱼网站会损害整个域名的信誉。
random.acme.com - 为租户工作负载注册独立的顶级域名(例如,用于租户,
acme.app用于品牌)。acme.com - 考虑使用PSL实现浏览器Cookie隔离;但它无法保护域名信誉。详见psl.md。
- 尽早提交PSL申请;审核可能需要数周时间。
- 选择租户识别策略
- 基于子域名:。需要通配符DNS。适用于大量租户的最简单方案。
tenant.yourdomain.com - 自定义域名:租户自带域名,通过CNAME指向你的平台。最适合付费/重度使用的租户。
- 基于路径:。无需为每个租户配置DNS/SSL,但会限制品牌化,且Cookie隔离更复杂。
yourdomain.com/tenant-slug - 选择一种主策略;将自定义域名作为升级选项提供。
- 定义隔离模型
- Cloudflare:对于不可信代码,优先使用租户专属Workers(Workers for Platforms调度命名空间)。除非你完全控制代码和数据,否则避免共享租户分支。
- Vercel:单一共享Next.js应用,通过进行范围限定。Middleware从主机名解析租户;所有数据查询都包含租户上下文。使用Postgres RLS实现纵深防御。
tenant_id
- 确定性路由
- Cloudflare:平台Worker负责路由;主机名 -> 租户ID -> 调度命名空间 -> 租户Worker。无映射时返回404。
- Vercel:Next.js Middleware提取主机名,将URL重写为动态分段。使用Edge Config实现亚毫秒级租户查询。无映射时返回404。
/domains/[domain] - 在两个平台上,租户都无法控制路由,也无法看到彼此的存在。
- 在技术栈中传递租户上下文
- Cloudflare:平台Worker解析租户信息,并在调度到租户Worker之前注入头信息或绑定。
- Vercel:Middleware在转发请求头中设置、
x-tenant-id、x-tenant-slug。Server Components通过x-tenant-plan读取;API路由从请求头读取。headers() - Middleware/平台Worker是唯一权威来源;绝不信任客户端提供的租户身份。
- 仅绑定必要资源
- Cloudflare:为每个租户配置最小权限绑定(数据库/存储/受限平台API),无共享全局状态。将新绑定视为显式变更;需重新部署以授予访问权限。
- Vercel:使用Edge Config存储租户配置(域名映射、功能标志、套餐信息)。通过Vercel SDK()管理域名。数据库连接通过
@vercel/sdk限定范围,或为每个租户单独配置数据库(如Neon)。tenant_id
- 支持自定义域名
- 提供DNS目标、验证所有权、存储映射,并按主机名路由。
- Cloudflare:使用Cloudflare for SaaS自定义主机名 + 托管证书。详见cloudflare-platform.md。
- Vercel:通过调用Vercel Domains API实现程序化域名CRUD + 自动Let's Encrypt SSL。通配符子域名需要使用Vercel域名服务器。详见vercel-domains.md。
@vercel/sdk - 自定义域名将信誉风险转移给租户,并自然形成用户细分(普通用户使用平台域名,重度用户使用自有域名)。
- 提供租户专属静态文件
- 、
robots.txt、sitemap.xml必须按租户区分;不要从llms.txt目录提供。/public - Cloudflare:在租户Worker中生成租户专属响应。
- Vercel:按域名分段使用路由处理器。详见vercel-platform.md。
- 将限制与套餐关联
- 将平台限制映射到定价层级;在API和UI中展示。
- 不要在请求中运行长时间任务;使用队列/工作流。
- 详见limits-and-quotas.md中的限制快照和源链接。
- 在最终确定架构或定价决策前,务必重新查阅官方文档中的限制说明。
- 以API为核心构建产品
- 所有功能均通过HTTP实现;UI仅用于运维/事件/计费。
- 平台逻辑保留在路由层(调度Worker或Middleware);租户内容处理请求。
- 如果某项功能仅在UI中可用,说明平台设计存在漏洞。
- 在不突破边界的前提下扩展
- 添加队列/工作流/容器作为可选模式。
- 保持路由明确,隔离性完好。
Deliverables
交付物
- Platform choice rationale: Cloudflare vs Vercel with justification
- Tenant identification strategy: subdomain, custom domain, or path-based
- Domain map: brand vs tenant domain, PSL plan, custom domain flow
- Isolation plan: per-tenant Workers or shared-app with tenant scoping
- Routing plan: hostname lookup, dispatch/rewrite logic, fallback behavior
- Tenant context flow: how tenant identity propagates through middleware/headers/DB
- Binding/config matrix: per-tenant capabilities and data access
- Limits-to-pricing map: CPU/memory/request/domain budgets per tier
- API surface + ops UI scope
- 平台选择理由:对比Cloudflare与Vercel并说明选择依据
- 租户识别策略:子域名、自定义域名或基于路径
- 域名映射:品牌域名与租户域名的区分、PSL计划、自定义域名流程
- 隔离方案:租户专属Workers或带租户范围限定的共享应用
- 路由方案:主机名查询、调度/重写逻辑、fallback行为
- 租户上下文流转:租户身份如何通过Middleware/头信息/数据库传播
- 绑定/配置矩阵:租户专属能力与数据访问权限
- 限制-定价映射:各层级的CPU/内存/请求/域名配额
- API接口范围 + 运维UI范围
References to load
需加载的参考资料
- Always load PSL submission and cookie isolation guidance: psl.md
- If platform is Cloudflare, load platform primitives and routing: cloudflare-platform.md
- If platform is Vercel, load platform primitives and routing: vercel-platform.md
- If platform is Vercel, load domain management and SSL: vercel-domains.md
- Load platform limits and plan mapping last: limits-and-quotas.md
- 始终加载PSL提交与Cookie隔离指导:psl.md
- 如果选择Cloudflare平台,加载平台原语与路由相关内容:cloudflare-platform.md
- 如果选择Vercel平台,加载平台原语与路由相关内容:vercel-platform.md
- 如果选择Vercel平台,加载域名管理与SSL相关内容:vercel-domains.md
- 最后加载平台限制与套餐映射内容:limits-and-quotas.md
Pre-commit checklist
提交前检查清单
- Platform chosen with clear rationale documented
- Tenant workloads off the brand domain; PSL decision + timeline set
- Tenant identification strategy chosen; custom domain upgrade path defined
- Isolation model defined: per-tenant Workers (Cloudflare) or shared-app + RLS (Vercel)
- Routing authoritative and tenant-blind; dispatch or middleware handles all traffic
- Tenant context flows through middleware/platform Worker only; no client-supplied identity trusted
- Custom domain onboarding defined with DNS target, verification, and cert provisioning
- Per-tenant static files (robots.txt, sitemap.xml) served dynamically
- Limits tied to billing; API parity with UI
- Limits snapshot refreshed from official docs and dated in planning notes
- 已选择平台并记录明确的选择理由
- 租户工作负载已与品牌域名分离;已确定PSL决策与时间线
- 已选择租户识别策略;已定义自定义域名升级路径
- 已定义隔离模型:租户专属Workers(Cloudflare)或共享应用+RLS(Vercel)
- 路由权威且对租户透明;所有流量由调度Worker或Middleware处理
- 租户上下文仅通过Middleware/平台Worker流转;绝不信任客户端提供的身份信息
- 已定义自定义域名上线流程,包括DNS目标、验证和证书颁发
- 租户专属静态文件(robots.txt、sitemap.xml)已实现动态提供
- 限制与计费绑定;API与UI功能一致
- 已从官方文档刷新限制快照,并在规划笔记中注明日期