← All projects CDC for Event-Driven Architecture

CDC for Event-Driven Architecture

Streaming

Moved a data platform from batch ETL to real-time streaming using Change Data Capture on MongoDB and Postgres, with reusable Python packages that hid the integration complexity from product teams.

pythonmongodbpostgrescdc

Overview

Our data platform ran on nightly batch ETL, which meant the rest of the system was always a few hours behind the database. I led a small team to replace that with Change Data Capture, so a change in MongoDB or Postgres becomes an event the moment it happens and everything downstream can react in real time.

Why we did it

The old approach leaned on updating several APIs at once whenever data changed, and that turns out to be fragile. One slow service or a dropped request and you end up with state that disagrees across the platform. We wanted something that kept downstream systems in sync without product teams hand writing fan out logic, survived network blips, restarts and deploys without losing its place, and told consumers enough about each event that they could read it correctly without knowing how the source stored it.

What we built

Two Python packages did most of the work. CDC-Watcher tails the change streams on MongoDB and Postgres and publishes every change as an event. CDC-Consumers sits on the other side and hands those events to product code, keeping the awkward parts like offsets, retries and schema handling out of sight.

There is also a CLI built with Click for running and inspecting watchers. We later exposed the same operations as Django management commands so they fit the workflows people already had.

// BATCH ETL → REAL-TIME STREAMING event stream MongoDB oplog Postgres WAL CDC-Watcher publishes change streams oplog · WAL CDC-Consumers hides offsets, retries · schema clean events out PRODUCT search index notifications cache refresh
Change events flow from MongoDB and Postgres through CDC-Watcher into an event stream, then CDC-Consumers deliver clean events to product features in real time.

Keeping it reliable

Each stream carries a resume token, a marker for the last event it processed. If a watcher dies, a link drops or a cluster goes down, it picks back up from that token instead of replaying old data or skipping new data. The one case it cannot resume from is a long outage. MongoDB’s op log has a fixed size, so if a watcher stays offline long enough for the log to roll over, there is nothing left to resume against and the stream restarts from now.

Deploys needed the same care. The watcher listens for SIGINT and SIGTERM, and on either signal it stops taking new work and waits, usually 30 to 60 seconds, for the messages already in flight to finish before it exits. Nothing gets dropped in the middle of a release.

Working with async

The watcher runs on asyncio, which keeps it fast but means events do not arrive in a tidy line. Messages move through an async queue, and we drop a sentinel into that queue to mark a safe point to save progress. Resume tokens get persisted when a sentinel comes through or on a short timer, whichever lands first, so the saved position never drifts far behind what has actually been handled.

Events and schemas

Published events land on RabbitMQ streams, which behave like append only logs, close to a Kafka topic, and are distributed and highly available. Alongside every event we store its schema in a dedicated cdc_schema table. When someone adds a field to a watcher, a new schema version is written automatically, so the change shows up downstream without anyone hand editing a migration.

That part is what made the system pleasant to build on. Because each event travels with its field types and structure, a new product or UI can start reading a stream and interpret it correctly without knowing anything about how the source database is laid out.

Impact

Product teams could subscribe to data changes without learning any of the CDC machinery underneath, and that is what let event driven features spread across the platform. The data stayed in sync in real time, the watchers recovered on their own after failures, and schema changes flowed through without manual migrations.

© 2026 Arnav Singh Chauhan
Built with Astro and the Astrofy template ⚡️
Chiku the cat
🐱 Konami unlocked! Chiku approves of you. (he approves of almost no one)