O que é?
Multi-tenant significa servir várias "casas" (tenants) com a mesma infraestrutura. Cada tenant é um cliente, um projeto, uma empresa — e os dados de um não podem aparecer pro outro. A questão é como você separa.
Existem 4 modelos clássicos. O SuperDB usa o quarto, um banco por projeto:
| Modelo | Como funciona | Isolamento | Custo |
|---|---|---|---|
Shared table + tenant_id |
Uma tabela users com coluna tenant_id |
Fraco — esquecer um WHERE vaza tudo |
Mínimo |
| Shared schema | Tabelas com prefixo tenant_a_users |
Médio — separadas mas no mesmo schema | Baixo |
| Schema-per-tenant | Schema proj_acme, proj_xyz no mesmo banco |
Forte, desde que toda permissão de todo schema esteja certa | Baixo |
| DB-per-tenant (SuperDB) | Um banco Postgres por tenant; no SuperDB, um por projeto, com o schema proj_acme dentro |
Máximo: o papel de um projeto nem conecta no banco de outro | Alto para quem opera (conexões e backups × N); no SuperDB, quem opera é a plataforma |
Com um banco por projeto, o isolamento não depende de toda permissão estar certa em todo schema: a consulta de um projeto roda no banco dele, e o banco de outro projeto não existe para ela. Operar um banco por projeto (conexões, backups, atualizações) é trabalho da plataforma, não seu.
Por que importa?
Multi-tenancy mal feita é uma das fontes mais comuns de incidentes de segurança em SaaS. Se você compartilha tabela e esquece um WHERE tenant_id = ?, vaza dados de outro cliente. Aconteceu com gigantes.
Um banco por projeto elimina essa classe inteira de bug:
- Sem consulta cruzada entre projetos: uma consulta enxerga só o banco em que está conectada; não existe
JOINcom a tabela de outro projeto - Políticas por projeto: cada projeto tem as próprias políticas de RLS
- Exportação por projeto: os dados de um cliente saem sem tocar os outros
- Migrations isoladas: a mudança num projeto não encosta nos demais
- Exclusão por projeto: apagar um projeto apaga o banco dele, e só ele
Vendendo pra empresa: "um banco de dados por cliente" é argumento técnico que a área de segurança de cliente B2B entende e aprova. Vale citar no questionário de segurança que o seu cliente mandar.
Como funciona no SuperDB
Quando você cria um projeto no painel (ou pela API / MCP), o SuperDB faz por baixo dos panos:
1. cria o schema proj_acme, os papéis de banco do projeto e as chaves
2. pouco depois, transfere o projeto para o banco dele, sozinho
3. a API do projeto passa a falar só com esse banco
A partir daí:
- Toda tabela que você cria pelo Studio vai pro schema
proj_acme, no banco do projeto - A API REST sabe qual projeto atender pela chave ou pelo token: o token carrega o schema do projeto, e a requisição para outro projeto é recusada
- RLS roda dentro do schema, com
auth.uid()referindo ao usuário daquele projeto
Quando usar (e quando não)
Um banco por projeto é o padrão do SuperDB e cobre os casos comuns sem você pensar. Mas vale entender quando separar clientes em projetos faz sentido e quando seria exagero:
Faz sentido quando…
- SaaS B2B — cada cliente tem dados sensíveis, não pode ver os outros (CRM, ERP, contabilidade)
- White-label — você vende a infra pra agências que revendem pra clientes finais
- Compliance forte: LGPD, SOC 2, ISO 27001. Auditorias costumam pedir isolamento entre clientes. O SuperDB não tem SOC 2 nem ISO 27001 (veja Segurança)
- Backups por cliente — quer poder exportar/restaurar 1 cliente sem tocar os outros
Talvez não precise quando…
- App single-tenant — você tem 1 produto pra todos os usuários (rede social, marketplace público)
Nota: mesmo num app single-tenant, o SuperDB ainda cria um schema proj_<slug>. O overhead é zero (Postgres não cobra por schema vazio), então não vale evitar.
Exemplos práticos
1. Criar um projeto gera schema novo
# Painel → Novo projeto → "acme" (ou pela API / MCP)
✔ Projeto "acme" criado.
Schema: proj_acme
URL: https://api.superdb.com.br
Anon key: eyJhbGciOi...
2. Signup no projeto X grava em proj_X.users
Um usuário do projeto acme que faz signup recebe, no corpo do login, um data_plane_token que já carrega o claim project_schema: proj_acme. É esse claim — não a URL, não um header que você monte — que decide qual schema a consulta enxerga. O isolamento é por construção: um token de acme não tem como apontar para outro tenant.
// `data_plane_token` vem no corpo do login, ao lado do `access_token`.
// É ele que a API de dados aceita — o access_token é só a sessão.
const { data_plane_token } = await login()
// Dados via fetch direto — api.superdb.com.br (sem /rest/v1/)
// O schema sai do claim project_schema do próprio token.
const res = await fetch('https://api.superdb.com.br/profiles', {
headers: { Authorization: `Bearer ${data_plane_token}` },
})
const profiles = await res.json()
3. Relatório de vários projetos: some na sua aplicação
Cada projeto está no próprio banco, então nenhuma consulta SQL atravessa projetos, nem com a service-role key. Para um relatório de vários clientes (uso global, cobrança), consulte cada projeto num job do seu servidor e some lá:
import { createClient } from '@superdb/client'
// Um par (projeto, chave de servidor) por cliente, guardado só no servidor
let total = 0
for (const { project, serviceKey } of clientes) {
const db = createClient(process.env.SUPERDB_URL!, serviceKey, { project })
const { count } = await db.from('events').select('*', { count: 'exact', head: true })
total += count ?? 0
}
Armadilhas comuns
Não existe consulta entre projetos. JOIN proj_a.users JOIN proj_b.orders não funciona com chave nenhuma: cada projeto está no próprio banco. Dado que precisa ser cruzado mora no mesmo projeto; relatório de vários clientes se soma na sua aplicação (exemplo 3).
- Mudança de estrutura vale por projeto. Uma migration muda só o projeto em que rodou. Para vários clientes com a mesma estrutura, os Groups clonam um template para cada cliente novo.
- Tipos, sequences e funções também são por projeto. Um enum
order_statuscriado emproj_anão existe emproj_b: crie em cada projeto (ou no template do Group).
Termos relacionados
- RLS — a camada de segurança dentro de cada schema
- Service-role vs anon: o que cada chave pode dentro do projeto
- PostgREST — como o REST sabe qual schema usar
- Glossário: multi-tenant
- Postgres docs — Schemas