Skip to main content
Overlay currently uses a single-customer deployment model. That means the deployment boundary is the tenant boundary:
  • A self-hosted enterprise gets one web runtime, one Convex deployment, one object-store namespace, and one secret set.
  • A managed-cloud enterprise also gets one dedicated deployment and backend set.
  • Multiple stakeholders inside that enterprise are users with roles, not separate tenants.
Do not onboard multiple enterprise customers into the same Convex deployment with the current schema.

Tenants Versus Roles

A tenant is a hard data-isolation boundary. In today’s architecture, that boundary is the deployment itself. Roles are authorization rules inside one tenant. A school should normally be modeled like this: Do not add tenantId just to represent students, teachers, parents, departments, or classes. Future RBAC should use roles, groups, memberships, and policy checks within the same deployment.

Deployment Modes

The current config schema rejects capabilities.multiTenant=true. Admin/system surfaces should report single-customer deployment; no tenant switcher or tenant-admin UI should appear.

Current Security Model

Single-customer deployment:
  • No tenantId column is required in Convex tables.
  • User-owned rows are scoped by userId inside that deployment.
  • API keys belong to a user in the deployment.
  • Webhook subscriptions and deliveries belong to a user in the deployment.
  • Storage keys and generated URLs are scoped to the deployment’s object-store namespace and user checks.
  • Operational isolation comes from separate Convex deployments, object-store buckets or prefixes, secrets, domains, logs, and provider credentials.
This is the required model for enterprise customers until shared multi-tenant deployment support exists.

API Keys And Webhooks

API keys:
  • Current behavior: API keys are deployment-local and user-owned through apiKeys.userId.
  • No tenant claim is encoded or enforced because the deployment is the tenant boundary.
  • A dedicated managed-cloud enterprise must have its own API_KEY_HASH_SECRET.
  • Shared multi-tenant requirement: API keys must include tenant ownership, tenant-aware scopes, tenant-aware rate-limit keys, tenant-aware audit entries, and validation that the key tenant matches the request tenant.
Webhooks:
  • Current behavior: webhook subscriptions and deliveries are deployment-local and user-owned through webhookSubscriptions.userId and webhookDeliveries.userId.
  • No tenant routing field exists because the deployment is the tenant boundary.
  • Shared multi-tenant requirement: webhook subscriptions, deliveries, event ownership, signing secrets, retries, and delivery runner queries must include tenant context.

Convex Table Tenant Decisions

These user-owned tables intentionally do not have tenantId today because the deployment is the tenant boundary. npm run check:tenant-boundaries verifies that every current userId-owned Convex table is listed here. The following tables are not user-owned tenant data today. They still need review before shared multi-tenant deployments, but the static check only requires explicit documentation for userId-owned tables:
  • processedWebhookEvents
  • rateLimitWindows
  • serviceAuthReplayNonces
  • sessionTransferTokens

Shared Multi-Tenant Checklist

Do not enable shared multi-tenant deployments until this checklist is complete:
  • Schema migration plan for adding tenantId to every user-owned table.
  • Backfill plan for existing rows.
  • Index expansion plan for every secondary, search, and vector index.
  • Tenant-aware auth/session claims.
  • Tenant-aware role and membership model.
  • Tenant-aware API keys, scopes, audit trail, and per-key/per-tenant rate limits.
  • Tenant-aware webhook subscription, delivery, retry, and signing-secret ownership.
  • Tenant-aware object-storage key namespace and public/share URL policy.
  • Cross-tenant negative tests for every domain service before enabling shared deployments.
  • UI policy for tenant switchers, unavailable states, and tenant admin surfaces.
Until then, use one deployment per enterprise customer.