Two Ways to Catch a Change

A medium Pipeline Design interview practice problem on DataDriven. Design the pipeline on the canvas: sources, transforms, storage and checks, then get feedback on it.

Domain
Pipeline Design
Difficulty
medium
Seniority
L5

Problem

Should we capture changes from our several production databases by reading each database's write-ahead log, or with triggers? Design the change data capture pipeline that replicates them into the warehouse, and make a concrete recommendation on the capture method for each source.

Two ways to watch the database. Each has a cost.

Business requirements

Worked solution and explanation

The call is made by the constraints

This is a load-and-loss question dressed up as a tooling debate. Anyone can name Debezium. What separates candidates is noticing that the stakeholders already ruled out triggers: the database team won't accept extra write load, fraud needs changes in minutes, and a deleted account must stay visible. Pick triggers and you double every application write, then discover a disabled trigger leaves the warehouse silently wrong.

Trigger-based capture
Every insert, update and delete fires a trigger that writes a second row inside the application's transaction. Peak load gets slower, and a DBA who disables the trigger at 3 AM creates a gap nobody sees. Deletes are only captured if you remember to write the trigger for them.
Log-based capture
A connector reads the write-ahead log or binlog the database already writes. No extra write path and no query load. Deletes arrive as ordinary DELETE events carrying the primary key, in commit order, beside inserts and updates.

Step 1: Capture once from the log

Put one log-based CDC node between source databases and the stream. It is the only thing that touches the sources, so the database team gets one replication slot to review instead of a trigger on every table. If one legacy source exposes no log, escalate that one source rather than retreating to triggers everywhere.

Step 2: Fan out from one change stream

Land the events in a single Kafka-style change stream. Fraud reads it with a Flink job in seconds, and analytics reads the same events with a Spark micro-batch every few minutes. Two independent extracts from the source would double the load and let the two teams disagree about what happened.

Step 3: Make deletes loud on both paths

Each consumer path applies a DELETE event as a soft delete, setting is_deleted and deleted_at on the warehouse row instead of removing it. Fraud can then query for deletions in the last day and see every closed account. A row that vanishes without a trace is the exact failure the requirement names.

Log-based capture runs once, then fans out to a real-time path and a 15-minute path. DELETE events ride the same stream and land as soft deletes.
  • source databases (source, PostgreSQL)
  • cdc log capture (transform)
  • change stream (queue, Kafka)
  • fraud stream soft delete (transform, Flink); freshness: real-time
  • fraud warehouse (storage, warehouse)
  • analytics loader soft delete (transform, Spark); freshness: < 15min
  • analytics warehouse (storage, warehouse)
  • fraud dashboard (consumer, Grafana)
  • analytics dashboard (consumer, Metabase)
  • source databases -> cdc log capture
  • cdc log capture -> change stream
  • change stream -> fraud stream soft delete
  • change stream -> analytics loader soft delete
  • fraud stream soft delete -> fraud warehouse
  • analytics loader soft delete -> analytics warehouse
  • fraud warehouse -> fraud dashboard
  • analytics warehouse -> analytics dashboard

Common follow-up questions