ADR 0002: Tenancy model — shared schema with RLS, routing for dedicated modes

Status: Accepted

Date: 2026-07-19

Context

The platform must support single-tenant, shared multi-tenant, dedicated-database, and regional-shard products through one contract.

Decision

  • Every tenant-owned row carries tenant_id.
  • Shared mode: PostgreSQL row-level security is enabled on tenant tables as defense-in-depth; application repositories filter by tenant first (RLS is the second layer). The application role does not own the tables and has no BYPASSRLS.
  • Tenant resolution order is fixed and non-spoofable: verified custom domain → mapped subdomain → signed session/token tenant claim → internal header from a trusted gateway. A public X-Tenant-ID header is never accepted.
  • Dedicated/regional modes: TenantRouter maps tenant → connection using the same schema and module registry.
  • TenantContext (see @vercia/kernel) is required in every request, job, event, cache key, file key, audit entry and query.

Consequences

  • Isolation is testable: modules/*/isolation.test.ts and property tests must prove cross-tenant denial.
  • Dedicated databases need no code changes, only routing configuration.