Architecture
O Block 3 fechou a decisão de arquitetura com evidência experimental, não por analogia:
| Approach | Best use | Problem |
|---|---|---|
| Raw CDC | audit / analytics | expõe mudanças físicas da base, não intenção de negócio |
| Curated Streams | normalização de CDC legado | exige transformação, estado e filtros explícitos |
| Transactional Outbox + Debezium | eventos de negócio | exige modelação explícita, mas preserva a intenção |
A razão central é simples: uma mudança física numa row não equivale
automaticamente a um evento semântico. O teste APPROVED → APPROVED produziu
updates raw, mas nenhum novo status event quando before/after permitiram
comparar o estado.
Caminho principal para eventos de negócio
flowchart TD
A[Application] --> B[PostgreSQL transaction]
B --> C[payments]
B --> D[outbox_events]
D --> E[Debezium]
E --> F[payment.events]
F --> G[Consumers]
payments e outbox_events são gravados no mesmo commit. O rollback do marker
outbox-rollback-proof-1789140000000 deixou o pagamento APPROVED, sem row
Outbox e sem marker Kafka. Quando o connector Debezium ficou offline, o commit
persistiu no PostgreSQL e o evento apareceu após a recuperação em
payment.events, partition 3, offset 0.
Raw CDC e normalização legada
flowchart TD
A[PostgreSQL] --> B[Raw CDC]
B --> C[audit / analytics]
B --> D[Curated Streams]
D --> E[normalized legacy events]
Curated Streams é uma camada de normalização controlada para CDC legado. Não é o caminho principal para novos eventos de negócio: a intenção deve ser modelada na transação através do Outbox.
What changed our architecture decision
Três provas alteraram a decisão de “plausível” para sustentada:
- Rollback: confirmou atomicidade entre mudança de negócio e Outbox.
- Debezium offline: confirmou persistência independente da disponibilidade momentânea do connector, desde que o WAL necessário seja preservado.
- Raw CDC: confirmou que mudança de estado físico não representa necessariamente intenção de negócio.
Limites da evidência
- EOS RU versus RC permanece QUALIFIED: houve record físico em
read_uncommittede ausência emread_committed, mas não foi provada uma transação abortada completa. - A duplicação ALO determinística e a deduplicação após replay continuam NOT PROVEN.
- Replay com novo
application.idtem event ID determinístico validado, mas o replay end-to-end permanece QUALIFIED. - Decoupling empírico com
internal_note, falha composta e métricas numéricas de latência/payload continuam NOT PROVEN.
Fonte factual no repositório: labs/kafka-connect-cdc/BLOCK3_REPORT.md,
EXPERIMENT_REPORT.md, ARCHITECTURE_DECISION.md e OUTBOX_RETENTION.md.