Architecture patterns
Change data capture
CDC turns committed database changes into events by reading the database's own replication log, which avoids dual writes. Learn how it works, and why an outbox table usually sits in front of it.
Most systems already have a database that is the source of truth. The question is how to get reliable events out of it. The naive approach is to write to the database and then publish to a broker. That is a dual write, and a crash between the two loses the event. Publishing first is worse, because the event may announce a change that never commits.
Concept
Change data capture (CDC) reads a database's own log of committed changes and publishes each change as an event. There is no second write for the application to get wrong.
The big idea
Every committed change in Postgres goes into the write-ahead log (WAL). In MySQL, it goes into the binlog. A CDC tool such as Debezium connects as a replication client, reads committed changes in commit order, and publishes them as events to Kafka.
Because CDC reads only the committed log, it never publishes a rolled-back change, and it never misses a committed one.
Walking through a change event
An order moves from pending to paid. Debezium publishes something like this:
{
"op": "u",
"source": { "table": "orders", "lsn": 23891004, "ts_ms": 1767225600000 },
"before": { "id": 8812, "status": "pending", "total_cents": 4900 },
"after": { "id": 8812, "status": "paid", "total_cents": 4900 }
}The event says what changed, in which table, at which log position. Consumers can compare before and after to see the difference.
Why an outbox usually sits in front
Raw row-change events expose your internal schema to every consumer. Rename a column, and every downstream team breaks. Two refinements fix this.
- The transactional outbox. Write a purpose-designed event row into an
outboxtable, in the same transaction as the business change. Have CDC publish only that table. Consumers get stable domain events, and you keep the atomicity of CDC. See the transactional outbox. - A translation layer. A small stream processor converts raw table changes into domain events before other teams see them.
Where CDC is used
CDC is the standard tool for several jobs. It migrates data between systems, feeds search indexes and data warehouses, and invalidates caches. The consumers on the other end are covered in batch and stream processing.
Common mistakes
- Publishing raw table rows to every team. You couple every consumer to your table design.
- Ignoring schema changes. A renamed column changes every event that carries it. Plan the change with the consumers.
- Writing the event outside the change's transaction. That brings the dual write back in.
Check yourself
1. Why does CDC avoid the dual-write problem? It reads the database's own log of committed changes, so there is no second write to fail.
2. Why put an outbox table in front of CDC? So consumers see stable domain events, not the internal layout of your tables.
Key takeaways
- CDC publishes committed database changes by reading the write-ahead log or binlog.
- It never publishes a rolled-back change, and it never misses a committed one.
- Raw row events couple consumers to your schema, so put an outbox in front.
Further learning
The Debezium documentation covers connectors, the outbox event router and the operational details.
Debezium documentationDebezium Documentation :: Debezium Documentationdebezium.ioNext, see what happens when the events themselves are the source of truth, in event sourcing.
Related
The transactional outbox
Update a database and publish an event without a dual write. Learn how the outbox commits the event with the change, how a relay publishes it, and how an inbox removes duplicates.
Events, commands and notifications
Commands ask one receiver to act, while events announce facts that anyone can react to. Learn the difference in coupling, and how thin and fat events trade consistency for independence.
Batch and stream processing
How to move and transform large data sets reliably. Batch jobs run over bounded data, streams run over events as they arrive, and the same ideas of time, state and idempotent writes apply to both.