Transactional Outbox
O Outbox transacional é o caminho recomendado para eventos de negócio no
KafkaPay. A aplicação grava payments e outbox_events na mesma transação
PostgreSQL; Debezium publica depois, a partir do WAL.
flowchart TD
A[Application] --> B[PostgreSQL transaction]
B --> C[payments]
B --> D[outbox_events]
D --> E[Debezium]
E --> F[payment.events]
F --> G[Consumers]
O que foi provado
| Prova | Evidência |
|---|---|
| Atomicidade | rollback deixou o pagamento APPROVED, sem row Outbox e sem marker Kafka |
| Debezium offline | commit persistiu; no restore, evento em payment.events, partition 3, offset 0 |
| Identidade | eventId foi preservado pelo EventRouter |
| Key e ordem | aggregate_id foi usado como key e os eventos commitados conservaram ordem Kafka |
| Múltiplos eventos | PaymentApproved e LoyaltyPointsGranted na mesma transação |
O marker do rollback foi outbox-rollback-proof-1789140000000. O marker de
recovery offline foi outbox-offline-proof-1789140100000. Enquanto o connector
estava indisponível, a row existia no PostgreSQL e o evento ainda não estava em
Kafka; depois da recuperação, apareceu no offset observado.
Outbox não é um publisher síncrono
O commit PostgreSQL não publica diretamente no Kafka. O EventRouter de Debezium
usa event_type para o tópico payment.events, id para a identidade do
evento e aggregate_id para a key. Se o connector estiver temporariamente
offline, o WAL/slot retém o progresso necessário; isso não elimina requisitos
de capacidade, retenção e monitorização.
Limites e retenção
Uma republicação pode continuar possível em cenários de replay ou crash depois
do ACK Kafka e antes da confirmação downstream. O Outbox não torna side effects
externos transacionais. A política de retenção, sem cleaner automático, está em
labs/kafka-connect-cdc/OUTBOX_RETENTION.md.
Para a decisão completa e as exceções observadas, consultar os relatórios do
lab kafka-connect-cdc no repositório.