O problema: um serviço precisa salvar um pedido no banco e publicar o evento PedidoCriado no Kafka. São dois sistemas, sem uma transação em comum:
- Salva e cai antes de publicar: o pedido existe, mas ninguém fica sabendo.
- Publica e o commit no banco falha: os outros serviços reagem a um pedido que não existe.
A solução: gravar o evento numa tabela outbox, no mesmo banco e na mesma transação do pedido. Um processo separado lê essa tabela e publica no broker.
BEGIN;INSERT INTO pedidos (id, status) VALUES (42, 'CRIADO');INSERT INTO outbox (aggregate_id, type, payload) VALUES (42, 'PedidoCriado', '{"id":42}');COMMIT;Ou as duas linhas existem, ou nenhuma. O relay que publica pode ser:
- Polling: um job que lê periodicamente os registros não publicados e marca os enviados.
- CDC: o Debezium lê o log de transações do banco e publica cada inserção na outbox, sem consultas extras.
Como o relay pode cair entre publicar e marcar o registro, o evento pode sair duas vezes: a garantia é de “pelo menos uma vez”, e os consumidores precisam ser idempotentes.
- Para se aprofundar: Transactional outbox (microservices.io)