Tenants

Tenants#

O Tenant é o cliente do SEU cliente. Um mesmo tenant_id isola 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 o tenant_id dos 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:

text
                                  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#

bash
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#

bash
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#

bash
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:

text
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#

  1. tenant_id está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.
  2. O MESMO tenant_id em todos os produtos"acme" no banco, no vetor, no storage e no cache. Consistência = sistema fácil de auditar.
  3. Um projeto por ambiente/produto SEU, nunca por cliente finalProdução, Staging. Cliente final é Tenant DENTRO do projeto, não um projeto. Projetos são poucos e duradouros; tenants são muitos.
  4. Dados que são SEUS ≠ de um cliente — recursos criados sem tenant_id ficam no nível do projeto (compartilhados). Reserve tenant_id para 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_id diferente 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.