DE//AGENT
Explore
Tutorial Lesson 6 of 10 · The Streaming Series community intermediate

Stream changes, not tables — CDC from Postgres into the lakehouse

The intermediate pattern that replaces nightly extraction: read the write-ahead log through Debezium, stream through Kafka, dedupe by LSN, and MERGE into Delta/Iceberg. Covers tombstones, decimal handling, and what a dropped replication slot costs you.

At a glance

When OLTP → lakehouse with freshness < 15 min; You need deletes/updates
Where CDC
Why Batch extraction from an OLTP database loads it and still misses deletes and mid-day changes — the WAL carries every change with an order you can rank on.

Learning objectives

  • Read the write-ahead log instead of polling source tables
  • Order events by LSN and dedupe before merging
  • Handle tombstones without losing history

What you need

  • A Postgres source with logical replication available
  • [object Object]

Steps

  1. Name the gap batch extraction leaves — it loads the data and still misses deletes and mid-day changes. (from pattern-postgres-cdc-lakehouse )
  2. Read the write-ahead log, not the tables — WAL → Debezium → Kafka → [dedupe by LSN] → MERGE into lakehouse. (from pattern-postgres-cdc-lakehouse )
  3. Configure Debezium with `decimal.handling.mode=string` to avoid precision loss. (from project-postgres-cdc-kafka-lakehouse )
  4. Read the stream, keep the latest event per key by (lsn, ts_ms); MERGE on the primary key; `op='d'` → soft delete with `_deleted_at`. (from project-postgres-cdc-kafka-lakehouse )
  5. Treat deletes as events — a delete is an event with `op = 'd'`; choose hard delete on merge, or soft delete + `_deleted_at` (required if you need history or audit). (from skill-cdc-merge-designer )
  6. Configure a logical replication slot safely. (from project-postgres-cdc-kafka-lakehouse )
  7. Know the watch item before going live — a dropped replication slot forces a full re-snapshot. (from pattern-postgres-cdc-lakehouse )

Check yourself

  • A row deleted in Postgres shows up in the lakehouse as an event with `op = 'd'` — applied as a hard delete or a soft delete with `_deleted_at`, not as a missing row.
  • Replaying the same batch produces an identical table, because events are ranked by (lsn, ts_ms) and deduped before the merge.

Worked example

Bring up the CDC stack — from project-postgres-cdc-kafka-lakehouse

make up  # postgres + kafka + connect + minio
make register-connector
make seed-mutations  # insert/update/delete

Check the replication slot — from runbook-cdc-stopped

SELECT slot_name, active, restart_lsn, confirmed_flush_lsn FROM pg_replication_slots;

The pipeline in one line — from pattern-postgres-cdc-lakehouse

Postgres WAL ─▶ Debezium ─▶ Kafka topic ─▶ stream dedupe ─▶ MERGE ─▶ Delta/Iceberg

Sourced from

Security scan

Last sweep 2026-10-24: 0 finding(s), 0 marked as examples.

Common gotchas

  • Replication slot dropped / WAL purged → full re-snapshot required.
  • Out-of-order events flip a value back → ordering used arrival time.
  • Never read the source tables on a schedule.

Production considerations

  • Alert on slot retained WAL and connector task failures.
  • Monitor source-vs-target row counts continuously.

Diagram

postgres cdc pipeline
   |
   |- Postgres WAL --> Debezium --> Kafka topic
   |
   |- dedupe by LSN --> latest event per key
   |
   |- MERGE on primary key; op='d' --> soft delete (_deleted_at)
   |
    --> Delta/Iceberg; alert on slot retained WAL + task failures

Registry stats

Verification community · Oct 21, 2026
Completeness 81
Trust multiplier ×1.25
Composite 34.15 · adequate
Freshness 3 days since last source check
Difficulty intermediate
Version 0.1.0
License CC-BY-4.0
Security flags none