Supabase Central Data Plane
Per-project databases are an anti-pattern here: every project standing up its own
Postgres/Supabase stack inside the sandbox loses persistence on workspace
teardown, fragments backups, and wastes capacity. The data plane must be one
central, persistent, self-hosted Supabase; projects attach a scoped slice of it
as a project asset, exactly like they attach a scoped Nexus registry or a
Dokploy service. (The sandbox has no container runtime — docker is hard-walled —
so there is no in-sandbox path to stand up a DB anyway.)
Two halves enforce this:
- Negative (shipped):
bundled_database_service_forbiddenwalls any agent handoff that bundles apostgres/supabase/… service into a project compose file. Agents cannot bring up their own DB; databases are provisioned on the project’s Dokploy plane through the service catalog, not from the sandbox. - Positive (this doc): the central Supabase stack + the
supabaseconnector + the project asset give projects a real, managed, persistent database to target withsupabase/migrations/.
Central stack (proper self-hosting)
Section titled “Central stack (proper self-hosting)”Run the official Supabase self-hosting compose as a single central stack (managed like the other central stacks — Dokploy/Nexus — not per project):
- Postgres (the durable data; backed up centrally) + Supavisor pooler
- Kong API gateway (port 8000) — single ingress for all project schemas
- Auth (GoTrue), PostgREST, Realtime, Storage (S3-compatible)
- Studio + postgres-meta, optional Logflare + Vector
Central secrets live in OpenBao (connectors/supabase), never in env defaults:
JWT_SECRET, SUPABASE_PUBLISHABLE_KEY (anon), SUPABASE_SECRET_KEY
(service_role), POSTGRES_PASSWORD, SECRET_KEY_BASE, VAULT_ENC_KEY,
PG_META_CRYPTO_KEY, S3 protocol keys.
Per-project tenancy = schema-per-project
Section titled “Per-project tenancy = schema-per-project”Supabase OSS is not natively multi-tenant (one stack ≈ one project). The standard way to share one instance across projects is schema isolation, not a stack per project:
- Each project gets a dedicated Postgres schema
proj_<slug>in the central DB. - A scoped DB role per project (owner of its schema) +
authenticated/anongrants limited to that schema; RLS enforces row scoping. - The schema is exposed through PostgREST via
PGRST_DB_SCHEMAS(project schema added to the served list) behind the central Kong gateway. - The project receives a connection lease (scoped connection string + scoped keys), short-TTL and rotated — the same lease model as the project service catalog uses for Dokploy-backed services.
The project’s supabase/migrations/*.sql run against its schema on the central
instance. Data persists centrally across workspace teardown.
The supabase connector
Section titled “The supabase connector”Declared in connector-catalog.json as a hybrid, project-scoped connector
(targets: ["supabase"]), mirroring Nexus. Role mapping uses Supabase’s real
roles:
| FractalOps role | Supabase role |
|---|---|
| project_owner / maintainer, solution_admin | service_role |
| project_contributor, team_member, solution_user | authenticated |
| project_viewer, solution_viewer | anon |
Actions (upsert_database_project_access / _team_ / _access) provision the
project schema + scoped role + grants + PostgREST exposure, and issue the scoped
connection lease.
Project asset
Section titled “Project asset”A project adds the central Supabase as an asset (a repository/asset binding,
requiredManagedServices: [postgres, auth, storage] already declared on the backend
golden template). Attaching the asset = provisioning the project schema + lease via
the connector. The project service catalog (service_catalog MCP / service add)
binds the workspace to that scoped schema, instead of a bare per-project postgres
stack.
Implementation steps
Section titled “Implementation steps”- Central stack topology — deploy the official Supabase compose as a central
stack (k8s/Dokploy), secrets in OpenBao
connectors/supabase. (infra) supabaseconnector executor —_supabase_executorinexecutor_factory: connect as admin,CREATE SCHEMA proj_<slug>,CREATE ROLE, grants, RLS, add toPGRST_DB_SCHEMAS, mint scoped lease. (connector)- Project asset binding — project-factory adds Supabase as a scoped asset and calls the connector on attach. (project-factory)
- Deploy-plane — point the project service catalog’s supabase binding at
the central instance schema instead of a bare
dokploy/postgresstack. (integration)
Step 0 (connector declaration) is done; the bundled_database_service_forbidden
wall already blocks the per-project-DB anti-pattern.