Design canvas — compose your CDC pipeline
Every CDC design choice — direct vs outbox, snapshot mode, cleanup, partition key, schema policy, sink dedup — maps to a specific failure it prevents; the right pipeline for a workload is the smallest set of choices that closes its actual failure set.
Every piece is on the table — log, slot, snapshot, schema registry, outbox, cleanup, partitioning, idempotency. The capstone move: compose them into a pipeline for a real workload and trace each choice back to the failure it prevents.
Scene 12
Design canvas — compose your CDC pipeline
- Watch
- Try it
- Predict
- Capture
Default canvas: microservice-events with outbox + INSERT+DELETE same-tx + aggregate_id + BACKWARD-with-aliases + by-event-id dedup. The verifier cycles three injections — watch each get absorbed and which slot does the absorbing.
Highlighted lines are the ones running in the diagram right now.
def evaluate(slots, workload, injection):match injection.id:case 'slot-grows':return broken(sceneRef=5) # no slot covers thiscase 'rename-column':return checkSchema(slots, workload)case 'snapshot-restart':return checkSnapshotSeam(slots, workload)case 'hard-delete-race':return checkOutboxCleanup(slots)case 'consumer-replay':return checkSinkDedup(slots)case 'cross-key-order':return checkPartitionKey(slots)
def smallestViablePipeline(workload):match workload:case 'search-index':# idempotent by document id; DDL churn is the riskreturn Slots(sourceMode='direct-cdc',schemaPolicy='BACKWARD-with-aliases',sinkDedup='by-table-pk-lsn')case 'audit-log':# history IS the product — never drop itreturn Slots(sourceMode='outbox',snapshotMode='initial',partitionKey='aggregate_id',sinkDedup='by-event-id')case 'microservice-events':# canonical: outbox + aliases + per-aggregate orderreturn Slots(sourceMode='outbox',schemaPolicy='BACKWARD-with-aliases',partitionKey='aggregate_id',cleanup='insert-delete-same-tx',sinkDedup='by-event-id')case 'read-model':# outbox is the deeper fix; aliases the band-aidreturn Slots(sourceMode='outbox',schemaPolicy='BACKWARD-with-aliases',sinkDedup='by-event-id')
# failure → absorbed-by slot (origin scene)# ---------------------------------------------------------------# slot-grows → (none — operational) (scene 5)# rename-column → sourceMode=outbox (scene 8)# rename-column (band-aid) → schemaPolicy=aliases (scene 7)# snapshot-restart → sinkDedup=by-event-id (scene 11)# audit-log + never → snapshotMode=initial (scene 6)# hard-delete-race → cleanup=insert+del-tx (scene 9)# consumer-replay → sinkDedup (any) (scene 11)# cross-key-order → partitionKey=aggregate (scene 10)# tenant_id / random key → (broken, no absorber) (scene 10)# direct-cdc + DDL churn → (broken, see outbox) (scene 8)
Where this sits in Build a CDC pipeline (Debezium + outbox)
Scene 12 of 12. Capstone: pick a workload (search index / audit log / microservice events / read model), configure the six slots, fire failures. The verifier traces each absorbed or broken outcome back to the scene that introduced the responsible component.
All 12 scenes in Build a CDC pipeline (Debezium + outbox) · Every curriculum