- English
- English
Appearance
Imagine an e-commerce application that stores product data in PostgreSQL. The same data turns out to be needed in many other places:
The most intuitive way to keep them in sync: every time the application finishes writing to the database, it also sends an event to Kafka and updates Elasticsearch. This pattern is called dual write, and this is where the problem begins.
Application: BEGIN -> UPDATE product -> COMMIT (success)
Application: send "product changed" event to Kafka (fails: network error)The database already holds the new price, but Elasticsearch still holds the old price. There is no mechanism that guarantees both writes succeed together, because two different systems are not inside one transaction. This kind of inconsistency is usually only discovered when a customer complains that search results do not match.
Change Data Capture (CDC) solves this problem by reversing the direction: do not let the application sync the other systems manually. Take the changes directly from the source of truth, which is the database.
Change Data Capture is a pattern to capture every data change in a database, whether INSERT, UPDATE, or DELETE, and then stream it as events that other systems can consume, in near real-time.
Three core characteristics of CDC:
DELETE, which is exactly the change most often missed by simple polling approaches.CDC can be implemented in several ways. The difference matters because it decides reliability and system load.
The simplest way: a job runs periodically and looks for data that changed since its last run:
SELECT *
FROM products
WHERE updated_at > :last_check
ORDER BY updated_at;This way is easy to understand and needs no extra tools, but it has basic weaknesses:
DELETE is invisible: a deleted row never appears in the query result, so the other systems never know that the product no longer exists.updated_at column maintained consistently in every table, which is often forgotten in older code.A database trigger listens to every change and writes its record to a special table, then another process reads that table. This way captures DELETE and is more timely, but triggers add load inside the database and are often forgotten during schema maintenance.
The most efficient way: take the changes directly from the change log the database already writes naturally, which is the WAL in PostgreSQL or the redo log in MySQL InnoDB.
Further reading
The WAL is an append-only log the database writes to disk for every change as a durability guarantee. To understand how it works, including why writing to this log is fast and how it relates to COMMIT, read the article Write-Ahead Log: Why Databases Write Twice but Stay Fast.
Log-based CDC works with a simple principle: the database already records every change in the WAL, you only need to read it again. No repeated queries, no extra triggers, no updated_at column to maintain. This is why almost every modern CDC tool, such as Debezium, uses this approach.
The full flow, component by component:
{ "before": { "price": 100000 }, "after": { "price": 120000 }, "op": "u" }. The op value explains the type: c (create), u (update), or d (delete).Two concepts are important to understand here:
The basic difference is the number of writers:
COMMITted, its event can definitely be emitted. If the transaction is rolled back, the WAL produces no event, and no other system ever knows about that change.Consistency between systems is no longer guarded by application code, but by the architecture.
CDC fits needs like these:
DELETE.On the other hand, do not use CDC when the need is simple: to validate data between systems once a day or to run a periodic report, simple polling or a direct query is enough and much cheaper to operate.
Operational caution
A log-based CDC connector reads from a replication slot. If the connector dies for a long time and the slot is not monitored, the WAL will pile up because the database does not dare clean a log that has not been read, and the database disk can become full. Monitor the consumption lag and the slot size in your monitoring.
INSERT, UPDATE, DELETE) from a database and streams it as events to other systems, in near real-time.DELETE and adds query load. Log-based CDC is the most efficient approach.