Case: como o catcher-agents roda banco,
vetores e MCP no Catcher Data
A pergunta certa para qualquer plataforma de infraestrutura é: vocês usam isso? Aqui a resposta é verificável. O catcher-agents, produto de agentes de IA da família Catcher, roda em produção sobre o Catcher Data — e a wiki de engenharia da própria plataforma vive no nosso cloudwiki, consultada e atualizada por agentes de IA todos os dias. Este post documenta a arquitetura do consumo e as três lições que só produção ensinou.
O princípio: operar o que vendemos
Vender infraestrutura gerenciada que a própria empresa não usa seria uma bandeira vermelha grande demais. Quem opera o produto todos os dias conhece os cantos que nenhum checklist de QA cobre: o erro que só aparece com carga real, a métrica que mente, a migração que resolve dar errado de madrugada. Por isso a regra aqui é estrutural: os produtos da família Catcher rodam sobre o Catcher Data antes de qualquer material de vendas citar o recurso.
Este post documenta o caso mais completo. O catcher-agents — a plataforma de agentes de IA da família — roda em produção sobre o Catcher Data. E a wiki de engenharia do próprio Catcher Data roda no cloudwiki, o produto de knowledge base da plataforma. Dogfooding em duas camadas.
O setup do catcher-agents em produção
O catcher-agents precisa de duas fundações caras de operar bem: um banco relacional para o estado da plataforma e um banco vetorial para a memória semântica dos agentes. As duas rodam como instâncias dedicadas do Database gerenciado na região de São Paulo (GCP southamerica-east1):
| Instância | Engine | Papel |
|---|---|---|
agents-db |
MySQL 8, dedicada, tier db-f1-micro | Estado da plataforma: contas, agentes, execuções |
agents-pg |
PostgreSQL 16 + pgvector, dedicada, tier db-f1-micro | Coleções de vetores com ingestão de arquivos — a memória dos agentes |
As duas instâncias foram provisionadas pelo mesmo console e pela mesma API que qualquer cliente usa. Sem atalho interno, sem acesso direto ao projeto GCP por baixo do pano: se o fluxo de provisionamento, credencial ou conectividade tiver um degrau quebrado, o time tropeça nele antes do cliente.
A escolha de dois engines não é indecisão; é adequação. O estado da plataforma — contas, agentes, execuções — é carga transacional clássica, e o MySQL 8 a serve bem. A memória semântica exige o pgvector, que vive no Postgres. Em vez de forçar tudo num engine só, o case usa cada um no que faz melhor — e a plataforma provisiona os dois pelo mesmo fluxo, com a mesma superfície de credencial e backup. Para quem avalia, esse é um dado útil: a decisão MySQL versus Postgres deixa de ser uma aposta de plataforma e vira uma escolha por workload.
Dois pontos honestos sobre a tabela. Primeiro, o tier: db-f1-micro é a menor máquina da linha, e isso é proposital — o case prova o caminho gerenciado completo (provisionamento, credencial, backup, conectividade) com o custo mínimo, e subir de tier é uma operação, não uma migração. Segundo, as coleções do Vector não são fixture de demo: são coleções reais, com ingestão de arquivos reais, servindo busca para agentes em produção.
A arquitetura do consumo
Em uma figura textual, o consumo inteiro — quem chama o quê, e por qual porta:
catcher-agents (produção)
│
└──► data-api.catcher.one (a mesma API pública de qualquer cliente)
│
├── agents-db MySQL 8 dedicado (db-f1-micro)
│ estado: contas, agentes, execuções
│
└── agents-pg Postgres 16 + pgvector dedicado (db-f1-micro)
coleções de vetores, ingestão de arquivos,
busca híbrida (memória dos agentes)
agentes de dev do Catcher Data
│
└──► MCP · data-api.catcher.one/v1/mcp
│
└── cloudwiki wiki de engenharia (72+ páginas)
hospedada no shared Postgres tier
Três leituras desse diagrama. Primeira: o catcher-agents não fala com o GCP — fala com a data-api, pela mesma superfície pública, com os mesmos limites e as mesmas credenciais que valem para qualquer conta. Não existe um caminho privilegiado que esconda atrito de nós mesmos.
Segunda: os dois modos de hospedagem aparecem no mesmo desenho. O produto irmão roda em instâncias dedicadas; a wiki interna roda no shared tier — a colocação compartilhada em que várias empresas dividem um Postgres, cada uma isolada no seu próprio database. O case cobre, na prática, as duas ofertas do catálogo.
Terceira: o MCP não aparece como canal de demonstração, e sim como via de trabalho. É por ele que os agentes de IA que desenvolvem o Catcher Data leem e escrevem a wiki de engenharia, dezenas de vezes por dia. Se o MCP degradar — latência, auth, uma tool quebrada —, o desenvolvimento da própria plataforma trava no mesmo instante.
A segunda camada: a wiki que governa o nosso desenvolvimento
O dogfooding mais interessante não é o do produto irmão — é o nosso, interno. A wiki de engenharia do projeto Catcher Data, com mais de 72 páginas de conhecimento (arquitetura, decisões, runbooks, gotchas de operação), roda no cloudwiki, sobre o shared Postgres tier da própria plataforma.
Ela não é documentação decorativa. Os agentes de IA que desenvolvem o Catcher Data a consultam e atualizam via MCP todos os dias, com dois gates obrigatórios no fluxo de trabalho:
- Consulta antes de implementar. Antes de escrever código, o agente pergunta à wiki —
wiki_ask,wiki_search— se aquilo já existe, onde está implementado e qual decisão governa a área. - Write-back depois. Feature entregue, decisão tomada ou comportamento alterado viram atualização de página no mesmo ciclo de trabalho, antes do push.
Na prática, a busca híbrida, o wiki_ask e o Knowledge Refinery são exercitados diariamente pelo nosso próprio time de agentes, sobre um corpus que muda quase todo dia. Se o retrieval degradar, quem sente primeiro somos nós — no mesmo dia, no meio de uma tarefa. Um agente que recebe uma resposta errada da wiki implementa em cima de premissa errada, e o custo aparece no code review seguinte. Poucos loops de feedback são tão curtos.
Três lições que só produção ensina
Dogfooding só tem valor se os bugs e as lições forem admitidos em público. Três exemplos reais deste case — nenhum deles aparece em staging, em demo ou em teste sintético.
1. A memória "real" do Postgres não é a que o sistema operacional mostra. No monitoramento de instâncias, a leitura de memória do MySQL tem uma âncora natural: o buffer pool, dimensionado e observável. Quando a instância Postgres do catcher-agents entrou no painel, o mesmo olhar produzia um número sem sentido — a memória vista pelo OS fica encostada em 100% o tempo todo, porque o page cache do kernel absorve tudo que sobra. Isso não é pressão de memória; é o kernel fazendo o trabalho dele. O sinal que informa de verdade é a ocupação dos shared buffers, lida via pg_buffercache — uma semântica diferente da do buffer pool do MySQL, que exige coleta e interpretação por engine. Corrigimos a leitura no painel. Sem uma instância Postgres real observada de perto, o gráfico enganoso teria chegado primeiro a um cliente.
2. Migração com janela de escrita se resolve com merge, não com cópia. Parte dos dados do case começou no shared tier e foi movida para as instâncias dedicadas. Entre o snapshot inicial e a virada houve janela de escrita: os dois lados receberam gravações, e ao comparar, nenhum lado era superset do outro — copiar em qualquer direção descartaria linhas de alguém. A reconciliação foi um merge idempotente com INSERT ... ON CONFLICT DO NOTHING: a união dos dois lados, reexecutável quantas vezes fosse preciso, preservou tudo. A lição generaliza: em migração de base viva, planeje a reconciliação como merge desde o início, e desconfie de qualquer plano que assuma que um dos lados está completo. Essa lição virou página na wiki interna, seguindo o gate de write-back.
3. Teste que não roda não protege. Parte da suíte era gated: testes de integração que só executam quando flags e credenciais de ambiente estão presentes. A armadilha é que gated e nunca executado são, na prática, a mesma coisa — a suíte fica verde, o caminho real fica descoberto, e a confiança no verde é falsa. Foi a verificação E2E viva, rodando contra o ambiente de produção com dados reais, que pegou o que o fake não pegava: o comportamento real do serviço diferia do stub que os testes usavam. A regra que ficou no processo: caminho crítico tem verificação viva contra o ambiente real, executada de verdade a cada entrega — o teste gated é complemento, nunca a linha de defesa.
O fio comum das três lições: nenhuma é detectável por teste sintético. A métrica de memória só mente diante de um Postgres real sob carga real. A janela de escrita só existe quando há escrita de verdade acontecendo durante a migração. O gap entre o stub e o serviço só aparece quando alguém exercita o serviço. O instrumento que encontra essa classe de problema é um workload de produção com consequências — e cada achado virou artefato: correção no painel, página na wiki, regra no processo de entrega.
E há o que precisava não quebrar enquanto tudo isso rodava: a suite de pentest da plataforma — cross-tenant, auth, RBAC e injection — fecha em 114/114 PASS contra o ambiente vivo. O banco do catcher-agents e a nossa wiki interna vivem nesse mesmo ambiente, sob as mesmas regras de isolamento que valem para qualquer cliente.
O contrato implícito do dogfooding
Todo fornecedor promete confiabilidade; o papel aceita qualquer SLA. O compromisso verificável é de outra natureza: se o Catcher Data cair, o catcher-agents cai junto — o estado das contas, a memória vetorial dos agentes e a wiki que orienta o nosso próprio desenvolvimento ficam indisponíveis ao mesmo tempo. Nosso downtime é o downtime deles. Não existe versão dessa arquitetura em que a gente descubra o problema depois de você.
Isso alinha incentivos de um jeito que contrato nenhum alinha. A latência que incomoda o cliente incomoda o nosso agente na tarefa seguinte. A métrica enganosa no painel engana primeiro o nosso plantão. O upgrade que exigiria downtime longo é impraticável para nós pelos mesmos motivos que seria para você. Quando o time prioriza o backlog, os itens que doem em produção já doeram aqui — não precisam de um ticket de suporte para existir.
O contrato implícito, dito sem rodeio: operamos na mesma infraestrutura, pela mesma API, sob as mesmas regras de isolamento — e por isso cada melhoria de confiabilidade é, antes de tudo, autointeresse.
Por que isso importa para quem está avaliando
Vale também dizer o que o dogfooding não prova. Ele não substitui a sua avaliação de escala — a nossa carga é a nossa, não a sua. O que ele elimina é a classe de problema mais comum em plataforma nova: o caminho de primeiro uso quebrado, a métrica que ninguém olhou, a feature que só funciona na demo. Registro, provisionamento, credencial, ingestão, busca e MCP são percorridos aqui todos os dias, por gente que não tem como ignorar o atrito.
Os números do case, para deixar auditável o que este post afirma:
- 6 produtos numa API: Database, Vector, Cache, Storage, Wiki e MCP;
- 2 instâncias dedicadas em produção no case do catcher-agents — MySQL 8 e Postgres 16 com pgvector — na região de São Paulo;
- 72+ páginas na wiki interna de engenharia, servidas pelo cloudwiki sobre o shared tier;
- 114/114 na suite de pentest, cobrindo cross-tenant, auth, RBAC e injection.
Sem número redondo de marketing. Números de operação, do tamanho que são.
Rode no que a gente roda
Provisione um banco gerenciado, uma coleção de vetores ou uma wiki com RAG na região de São Paulo. É o mesmo caminho que o catcher-agents usa em produção.