en
· 4 min de leitura

O banco de dados não é sua camada de integração

Dois sistemas que compartilham um banco são um sistema com dois pipelines de deploy e nenhum contrato. Veja como sair dessa.

architecturedata

O padrão de integração mais caro que encontro em auditorias é também o mais invisível. Duas aplicações, às vezes cinco, todas conectadas ao mesmo banco. Nenhuma API entre elas. As tabelas são o contrato, e ninguém escreveu o contrato.

Sempre começa inocente. A ferramenta de relatórios precisa dos dados de pedidos, então ganha um usuário somente leitura. O novo backend do app mobile precisa atualizar perfis de clientes, então ganha permissão de escrita naquela tabela específica. Dezoito meses depois há sete consumidores, três deles escrevendo, e renomear uma coluna exige reunião com quatro times e janela de manutenção.

Por que parece de graça e não é

Compartilhar um banco parece de graça porque não há código para escrever. Os dados já estão lá. É só conectar. O custo aparece depois, em três lugares específicos.

Mudanças de schema viram negociações. O time dono da tabela de pedidos não consegue adicionar uma coluna NOT NULL, dividir uma tabela ou mudar um enum sem conhecer todo leitor e todo escritor, e nunca conhece todos. Então o schema congela. O congelamento é o custo real: o módulo que deveria evoluir mais rápido vira o que não consegue se mover.

Invariantes viram algo impossível de garantir. A aplicação de pedidos sabe que um pedido em status 'pago' precisa ter uma linha de pagamento. O script de relatórios que corrige 'dados ruins' nas sextas à tarde não sabe. Agora as premissas da própria aplicação são violadas por escritas que ela nunca vê, e os bugs aparecem na aplicação, onde ninguém procura uma causa de fora.

Performance vira destino compartilhado. Uma query de analytics que varre quarenta milhões de linhas não trava nada, em teoria. Na prática, ela expulsa o working set do cache, satura o I/O e deixa o checkout lento exatamente no momento em que o financeiro roda os relatórios de fechamento. Não existe rate limit, timeout ou circuit breaker entre um cliente SQL e uma tabela.

A regra do dono dos dados

Toda tabela tem exatamente uma aplicação que escreve nela. Essa aplicação é a dona. Todo o resto recebe os dados por algo que a dona controla: uma API, um fluxo de eventos publicado, um read model replicado que a dona constrói e versiona de propósito. Essa é a regra inteira, e ela é aplicável com permissões de banco, que é a parte que a maioria dos times pula.

A dona pode mudar suas tabelas livremente, porque o único consumidor do schema bruto é ela mesma. A forma publicada, a resposta da API ou o payload do evento, é versionada e estável. Esse é o contrato. Ele pode ser escrito, testado e evoluído com janela de depreciação.

Saindo sem reescrever

Você não precisa construir um service mesh. A migração que costumo recomendar tem quatro estágios, e cada um tem valor por si só.

  • Inventário: ligue o log de queries ou use as estatísticas de conexão do próprio banco para listar toda aplicação e todo usuário que toca cada tabela. A maioria dos times se surpreende com a lista.
  • Congele as escritas: revogue permissão de escrita de todo não-dono. Dê a eles um endpoint ou uma fila no lugar, uma tabela por vez, começando pela que muda com mais frequência.
  • Substitua leituras por views ou um read model: para consumidores que só precisam de dados, exponha uma view versionada ou uma tabela replicada que a dona alimenta. A view é o contrato; as tabelas por baixo viram privadas.
  • Revogue o acesso direto por completo e apague os usuários extras do banco. Se um consumidor ainda precisa de SQL bruto, isso é sinal de que precisa de um produto de dados de verdade, não de um login.

O estágio de congelar escritas entrega a maior parte da segurança. Quando só uma aplicação escreve, as invariantes voltam a ser garantíveis e o schema pode começar a se mover. Leituras podem ficar em views por muito tempo sem grande prejuízo.

A exceção que sempre aparece

'Mas é o mesmo time.' Tudo bem. Se um time é dono das duas aplicações e dos dois schemas, o risco é menor. Não é zero. As duas aplicações ainda vão fazer deploy separado, o que significa que vai existir uma janela em que uma tem as expectativas do schema novo e a outra não. É nessa janela que a indisponibilidade mora. Se você realmente não consegue separá-las, pelo menos faça toda mudança de schema retrocompatível e suba o escritor primeiro. Mas seja honesto: o que você tem é um sistema só, e pare de chamar de dois.

O banco de dados é um lugar fantástico para guardar dados. É um lugar péssimo para negociar entre times. Coloque a negociação em algum lugar que você consiga versionar.