O Desafio do Dual Write em Sistemas Distribuídos

Em arquiteturas monolíticas, atualizar a base de dados e notificar outros componentes sobre uma alteração costuma ocorrer dentro do escopo de uma única transação ACID local. Se a gravação no banco falhar, nenhum evento é emitido; se o evento falhar, o banco executa o rollback automaticamente. Em uma arquitetura baseada em microsserviços e orientada a eventos (Event-Driven Architecture), essa simplicidade deixa de existir. Frequentemente, um serviço precisa realizar duas ações distintas em uma mesma operação de negócio: persistir o estado atual em seu banco de dados local e publicar um evento em um intermediário de mensagens (Message Broker como Apache Kafka ou RabbitMQ). Tentar executar essas duas gravações de forma independente na aplicação gera o clássico problema do Dual Write (Escrita Dupla). Se o banco de dados confirmar a gravação, mas a rede ou o broker falharem logo em seguida, o estado do banco ficará inconsistente com os demais serviços. Se a aplicação inverter a ordem e publicar o evento primeiro, mas a gravação no banco falhar, serviços externos processarão uma alteração que nunca existiu na fonte primária.

A Abordagem Tradicional: Escrita Dupla Direta na Aplicação Historicamente, a tentativa de resolver esse problema baseou-se na gravação sequencial direta realizada pelo código da aplicação, por vezes englobada em blocos de tratamento de exceções (try-catch) convencionais. O fluxo tradicional tenta persistir a entidade no banco de dados relacional ou NoSQL e, imediatamente no passo seguinte, chama a biblioteca do cliente de mensagens para publicar o evento na rede.

Limitações da Escrita Dupla Direta

  • Inconsistência de Dados (In-doubt State): Falhas de rede, queda do contêiner ou indisponibilidade do broker entre as duas operações resultam em dados salvos no banco sem a devida notificação para o ecossistema;
  • Falta de Atomicidade Distribuída: Não é possível agrupar a gravação no SGBD e a chamada de rede ao broker dentro de uma mesma transação transacional garantida;
  • Complexidade na Aplicação: A camada de código de negócio passa a lidar diretamente com tratamento de retentativas e recuperação de falhas de infraestrutura de mensageria;
  • Riscos em Ambientes Concorrentes: Falhas em retentativas síncronas podem gerar duplicação ou desordenamento no envio dos eventos.

A Abordagem Moderna: Transactional Outbox Pattern O padrão Transactional Outbox elimina o problema do Dual Write aproveitando a própria capacidade transacional do banco de dados local do microsserviço. Em vez de enviar o evento diretamente para o broker de mensagens durante o processamento da requisição, a aplicação grava a mensagem em uma tabela (ou coleção) auxiliar no mesmo banco de dados local, denominada Outbox Table, utilizando a mesma transação ACID que salva a entidade de negócio.

Como Funciona o Mecanismo

  1. Transação Única: A aplicação inicia uma transação no banco local, grava as alterações da tabela de negócio e insere o evento na tabela Outbox. Ambas as gravações acontecem atomicamente: ou ambas são salvas, ou nenhuma é.
  2. Separação de Responsabilidades: A requisição do usuário é concluída com sucesso imediatamente após a confirmação do banco de dados local.
  3. Publicação Assíncrona: Um componente separado (Publisher/Relay) lê os registros pendentes da tabela Outbox e os publica no broker de mensagens.
  4. Confirmação: Após a publicação ser confirmada pelo broker, o registro na tabela Outbox é marcado como processado ou removido.

Estratégias de Implementação do Publisher (Relay) Existem duas abordagens predominantes para mover as mensagens da tabela Outbox para o broker de mensagens.

Polling Publisher (Worker de Consulta) Um processo em segundo plano (Worker/Cron) executa consultas periódicas (SELECT) na tabela Outbox em busca de eventos não processados, envia os dados para o broker e atualiza o status na tabela. Vantagens:

  • Simplicidade de implementação utilizando linguagens e frameworks padrão;
  • Funciona em qualquer banco de dados relacional convencional.

Desvantagens:

  • Ineficiência e overhead no banco de dados devido a consultas constantes (polling);
  • Maior latência na entrega do evento dependendo do intervalo de consulta;
  • Risco de concorrência se existirem múltiplas instâncias do worker rodando simultaneamente.

Change Data Capture – CDC (Captura de Mudanças no Log) Ferramentas especializadas em CDC (como o Debezium) monitoram diretamente o log de transações do banco de dados (Transaction Log / WAL / Redo Log). Quando uma nova linha é inserida na tabela Outbox, a ferramenta captura a alteração diretamente do log e a envia para o broker sem consultar a tabela via SQL. Vantagens:

  • Latência de publicação próxima do tempo real;
  • Zero overhead de consultas SQL adicionais sobre o banco de dados;
  • Desacoplamento total do processo da aplicação.

Desvantagens:

  • Requer infraestrutura adicional e configurações avançadas no SGBD para acesso ao log transacional.

Quando Utilizar Cada Abordagem? Utilize Escrita Dupla Direta quando:

  • O sistema for de pequeno porte e a eventual inconsistência entre o banco e as mensagens puder ser tolerada ou corrigida manualmente;
  • A perda pontual de eventos não impactar os fluxos financeiros, regulatórios ou operacionais do negócio.

Utilize Transactional Outbox com Polling quando:

  • A garantia de entrega das mensagens for obrigatória;
  • O volume de transações for moderado e a infraestrutura for simplificada;
  • Não for possível instalar componentes de CDC no banco de dados.

Utilize Transactional Outbox com Change Data Capture (CDC) quando:

  • O sistema operar em alta escala e exigir publicação de eventos com baixíssima latência;
  • A consistência de dados entre os microsserviços for um requisito crítico de arquitetura (At-least-once delivery);
  • A arquitetura for fortemente orientada a eventos (Event-Driven) com brokers como o Apache Kafka.

Na prática, o padrão Transactional Outbox associado ao Change Data Capture tornou-se a solução definitiva para garantir resiliência e atomicidade na integração entre banco de dados e brokers de mensagens em arquiteturas Cloud Native.

Quer uma solução personalizada para seu negócio?

Nossos especialistas em cloud computing analisam seu caso e criam uma estratégia sob medida.

Compartilhe essa publicação
Sobre o autor

Emanuel Nerys

Sou Arquiteto Cloud na KXC, focado em desenhar e implementar arquiteturas multi-cloud resilientes e de alta disponibilidade. Garanto o alinhamento de infraestruturas complexas com as melhores práticas de mercado, integrando segurança de ponta a ponta e cultura DevOps. Atuo na liderança técnica de ambientes altamente dinâmicos e automatizados, com forte domínio em Kubernetes.

Ver perfil e posts