MySQL CDC to PostgreSQL Final State Guide
June 2026
MySQL to PostgreSQL is an integration where row-based source fidelity meets a destination that reconciles through staging and ON CONFLICT.
Short Answer
MySQL CDC to PostgreSQL works by reading row-level binlog events from MySQL and applying them through PostgreSQL staging tables plus INSERT ... ON CONFLICT reconciliation. Skippr creates a _skippr_order_token TEXT column and a tombstone table automatically, so the PostgreSQL target only accepts a mutation when its token is newer than the token already attached to that key.
For example, if orders.id 918 changes from shipped_at null to a real timestamp, MySQL emits an UPDATE_ROWS event with the full row image and Skippr stages that row for PostgreSQL. The final upsert updates id 918 only when the incoming token is newer. If a DELETE_ROWS event arrives later for that same key, Skippr writes the tombstone and removes the row from the target table.
Why Teams Struggle with This
This is one of the more straightforward source-to-destination combinations because both sides are relational, but the integration still depends on explicit CDC guarantees. MySQL has to emit the right row events, and PostgreSQL has to compare tokens inside the ON CONFLICT path rather than trusting batch arrival order.
- MySQL CDC requires ROW binlog format, FULL row images, and a replication user with the right privileges.
- The destination only stays correct if the PostgreSQL conflict key matches the logical row identity from MySQL.
- Staging tables are part of correctness because they support the guarded merge pattern described in the docs.
- Tombstones are what stop a deleted MySQL key from being restored by an older replayed insert.
How Skippr Handles It
Skippr keeps the contract compact. It stores the MySQL binlog filename and position after each committed batch, reuses that on restart, and then applies the row changes to PostgreSQL with staging plus ON CONFLICT and token comparison. This pipeline does not need a separate downstream deduplication story.
That makes it easy to inspect a single row across the path. You can identify the MySQL event type, the ordering point, and the exact reason PostgreSQL updated, ignored, or deleted the target row.
- MySQL CDC support for WRITE_ROWS, UPDATE_ROWS, and DELETE_ROWS.
- Durable resume behavior from stored binlog filename and position.
- PostgreSQL staging plus INSERT ... ON CONFLICT with token-based guards.
- Automatic tombstone tables for delete protection.
What the First Useful Version Looks Like
Use this integration when PostgreSQL is the current-state destination and MySQL remains the operational source.
The cleanest implementation starts by deciding whether the MySQL primary key is already the business key you want PostgreSQL to preserve.
