Tenants#
O Tenant é o cliente do SEU cliente. Um mesmo
tenant_idisola um cliente final em TODOS os produtos de dados — Database, Vector, Storage e Cache. Esta página é o modelo mental que amarra os quatro.
O modelo: Conta → Projeto → Tenant#
Tudo no Catcher Data se organiza em três níveis:
| Nível | O que é | Quem define |
|---|---|---|
| Conta (workspace) | Sua empresa dentro do Catcher Data — onde você faz login / de onde sai a API key. | Catcher (no cadastro) |
| Projeto | Agrupamento dentro da conta; tem infra própria (instâncias, coleções, buckets, cache) + billing + estratégia de tenancy. Crie via POST /v1/clouddb/projects. |
Você |
| Tenant (end-customer) | O cliente do seu cliente — um identificador (tenant_id / external_id) que VOCÊ escolhe para isolar cada cliente final. |
Você |
Terminologia. O cliente final se chama Tenant em todo o produto (Console, API, manuais). Em rotas mais antigas do Database ele aparece como "company"/"end-customer" (campo
external_id) — é o mesmo conceito que otenant_iddos demais produtos. No Console, a antiga aba "Clientes" agora é Tenants.
O eixo transversal#
O tenant_id é simplesmente uma string que você escolhe para cada cliente
final (um id interno, CNPJ, um slug como "acme"). Não é um recurso separado a
gerenciar — é uma etiqueta que você carrega. Use o MESMO tenant_id em
todos os produtos e cada um aplica o isolamento físico nativo daquela
tecnologia:
Projeto
┌──────────────┬───────────────┬───────────────┬───────────────┐
Database Vector Storage Cache
│ │ │ │
tenant "acme" ──┼───────────────┼───────────────┼────────────── (o MESMO tenant_id)
schema dedicado schema t_acme bucket dedicado chaves t:acme:*
ou company_id + role tr_acme (IAM) + ACL ~t:acme:*
| Produto | Como o Tenant é isolado | Como você ativa |
|---|---|---|
| Database (clouddb) | schema dedicado por tenant (schema_per_company) ou coluna company_id + filtro forçado (row_level) |
registre o tenant em POST /v1/clouddb/projects/{pid}/companies; o isolamento segue a strategy do projeto |
| Vector (cloudvec) | schema Postgres dedicado t_<id> + role de acesso tr_<id> |
informe tenant_id ao criar a coleção |
| Storage (cloudstore) | bucket GCS dedicado, isolado por IAM | informe tenant_id ao criar o bucket |
| Cache (cloudcache) | prefixo de chave t:<id>:* + ACL Redis ~t:<id>:* |
prefixe suas chaves no app (+ usuário ACL por tenant) |
Em todos os casos, tenant_id vazio/ausente = recurso de nível projeto
(compartilhado entre os seus clientes) — apropriado para dados que são SEUS, não
de um cliente específico.
Como ativar em cada produto#
Database — registre o tenant no projeto#
KEY="X-API-Key: ctc_…" ; B=https://data-api.catcher.one ; JS='Content-Type: application/json'
PID=<project-uuid>
curl -sX POST $B/v1/clouddb/projects/$PID/companies -H "$KEY" -H "$JS" \
-d '{"external_id":"acme","name":"Acme S.A."}'
Sob schema_per_company, registrar provisiona o schema do tenant (catcher_c_…)
sob demanda. Sob row_level, o tenant é registry-only e o app filtra por
external_id (a coluna company_id). Detalhes + endpoints: Database.
Vector — tenant_id na criação da coleção#
curl -sX POST $B/v1/cloudvec/projects/$PID/collections -H "$KEY" -H "$JS" \
-d '{"name":"docs","tenant_id":"acme"}'
A coleção passa a viver no schema dedicado do tenant; a busca naquela coleção só enxerga os vetores dele. Detalhes: Vector.
Storage — tenant_id na criação do bucket#
curl -sX POST $B/v1/cloudstore/projects/$PID/buckets -H "$KEY" -H "$JS" \
-d '{"name":"assets","location":"southamerica-east1","tenant_id":"acme"}'
O bucket fica dedicado ao tenant (isolado por IAM no GCS). Detalhes: Storage.
Cache — prefixo + ACL no seu código#
O Cache é control-plane only (seu app conecta direto no DSN; não há proxy de comando), então o isolamento por tenant é por convenção, aplicada no SEU código:
chave = "t:" + tenant_id + ":" + sua_chave → t:acme:sessao:123
Opcionalmente, crie um usuário ACL do Redis por tenant, restrito ao padrão
~t:<tenant_id>:*, para que aquele tenant não leia/escreva fora do próprio
prefixo. Referência do Cache: Cache.
Database: qual estratégia escolher?#
A escolha entre as duas estratégias do Database é feita por projeto (campo
strategy em POST /v1/clouddb/projects):
| Critério | row_level |
schema_per_company |
|---|---|---|
| Isolamento | lógico (filtro forçado) | físico (schema separado) |
| Ideal para | muitos clientes pequenos/homogêneos; SaaS típico | separação forte, auditoria/compliance, exportar/excluir 1 cliente isoladamente |
| Custo operacional | menor (um schema só) | maior (um schema por cliente) |
| Escala de nº de clientes | milhares | dezenas a centenas |
| "Apagar tudo de um cliente" | apagar as linhas dele | descartar o schema dele |
Regra prática: comece com row_level se você tem muitos clientes parecidos;
escolha schema_per_company quando um cliente exige separação forte por
contrato/regulação/auditoria. Se precisa das duas, crie dois projetos.
Recomendações#
tenant_idestável e opaco — use um id que nunca muda (não o nome comercial). É a cola que liga os 4 produtos; se muda, a ligação se perde.- O MESMO
tenant_idem todos os produtos —"acme"no banco, no vetor, no storage e no cache. Consistência = sistema fácil de auditar. - Um projeto por ambiente/produto SEU, nunca por cliente final —
Produção,Staging. Cliente final é Tenant DENTRO do projeto, não um projeto. Projetos são poucos e duradouros; tenants são muitos. - Dados que são SEUS ≠ de um cliente — recursos criados sem
tenant_idficam no nível do projeto (compartilhados). Reservetenant_idpara dado que pertence de fato a um cliente final.
Granularidade extra (Vector): por usuário final dentro de um tenant#
Para isolar por usuário final dentro de um tenant sem multiplicar coleções,
use o filter por metadata na busca do Vector
(ex. "filter":{"end_user_id":"…"}, AND entre as chaves). O tenant_id dá a
fronteira física (schema dedicado); o filter dá a fronteira lógica fina
dentro dela. Ver Vector.
Gotchas#
- Não crie um projeto por cliente final — cliente final é Tenant, não projeto.
- Não use
tenant_iddiferente em cada produto — quebra a ligação transversal. - Não use o nome comercial mutável como
tenant_id— use um id estável. - No Cache, prefixe sempre — sem
t:<tenant>:, chaves de clientes diferentes se misturam. - A estratégia de tenancy do Database (
row_level/schema_per_company) é imutável por projeto — escolhida na criação do projeto.