Blueprint
Infrastructure

Change data capture

Turn your primary database into a source of events without touching application code — the plumbing that lets one write feed a cache, a search index and an analytics warehouse.

01

What it is

CDC reads the transaction log of a database (Postgres WAL, MySQL binlog, DynamoDB Streams) and turns each committed change into an event on a message bus. Consumers subscribe to that stream and derive whatever they need: invalidate cache keys, update Elasticsearch, land a row in the data warehouse.

The interview value is knowing the alternative — dual writes — and why it's dangerous. If your app writes to the DB and separately writes to Kafka, one of those writes will occasionally fail while the other succeeds. CDC removes that failure mode by driving the event from the same log the database uses for its own durability.

Say this out loud

Every derived data store I have — cache, search index, analytics — hangs off CDC on the primary. That way the primary is the only place I write, and I never risk a dual-write drift.

03

The variants and when to pick each

Log-based CDC (WAL / binlog)

The best kind. A connector reads the database's replication log directly, emits every committed change as an event. Row-level, ordered per table, exactly the same source the DB's own replicas use — so it's as consistent as replication itself. Debezium, AWS DMS, and Postgres logical replication are the standard tools.

The events include before/after images for updates and a delete marker for deletes — enough to keep any downstream in sync without extra queries.

Trade-offThe connector must handle log retention: if it falls behind and the database has already rotated the WAL, you have to bootstrap from a snapshot. Ops overhead is real.

Trigger-based CDC

Database triggers on every table copy each change to a dedicated events table; a poller reads that table and publishes. Portable across engines that don't expose a log (or where you can't get replication permissions), and application-visible so debugging is easier.

The cost is that every write now writes twice — measurable overhead on hot tables, and triggers can cause surprising lock contention.

Trade-offTrigger overhead is small per row but multiplies on hot tables. Not viable for tables doing tens of thousands of writes per second.

Transactional outbox

Not strictly CDC, but the pattern people reach for when they can't get to the WAL. The app writes to an events table in the same transaction as the state change; a shipper polls that table and publishes to Kafka. Same effect as CDC without the WAL access.

This is the workhorse pattern for microservices without a shared database platform team.

Trade-offYou've moved the failure surface from dual-writes to outbox-processing — you still have to make sure the shipper doesn't emit twice (idempotency downstream).

Snapshot + stream: bootstrapping a new consumer

A new consumer joining months into the game can't start reading from the current log offset — it will miss the world's initial state. The standard bootstrap: consumer takes a consistent snapshot (SELECT * FROM table AS OF LSN X), then subscribes to the log from offset X and applies events forward. The two together give a complete replica.

Debezium handles this transparently with 'initial snapshot' mode; hand-rolled connectors need to implement the LSN-anchored snapshot manually.

Trade-offThe snapshot phase can be slow on large tables — an operational bottleneck when you're adding consumers to a busy database. Some connectors support parallel snapshots per table to help.
04

Numbers worth memorising

Replication lag under normal load~100 ms Postgres logical, ~50 ms MySQL binlog
Replication lag during heavy writesseconds to minutes if consumers can't keep up
WAL retentionhours to days depending on config; can't fall behind by more
Events per second capacity~10k-50k per Debezium connector; parallelise per table
Bootstrap snapshottable_size / throughput; minutes for GB, hours for TB
05

Where the interviewer pushes

First push: 'why not have the app write to both the database and Kafka?' Answer with the concrete failure: the write to Kafka happens after the DB commit, and the process crashes between them — the DB has the change, Kafka doesn't, downstreams silently drift. CDC eliminates this by design because the same log the DB uses for its own replication is the event source.

Second push: 'what happens if the consumer is down for a day?' The message bus buffers (Kafka retention is configured for this). If the outage exceeds retention, the consumer has to bootstrap from a snapshot again. Retention needs to be at least the longest tolerable consumer outage — usually a week, sometimes more for cold analytics jobs.

Shows up in

Found a bug or want more?

Tell me what's broken, missing, or wrong. Every message lands in my inbox.