Skip to main content
MySQL → PostgreSQL

Sync MySQL to PostgreSQL
with real-time binlog CDC.

Replicate MySQL to PostgreSQL using binlog row-format CDC — continuous streaming after an initial snapshot, with automatic type mapping. Migrate, replicate for analytics, or consolidate multiple MySQL databases into one Postgres.

TL;DR

rsync.ai connects to MySQL as a replica, reads binlog events in ROW format (GTID or file+position), snapshots your tables, then streams all subsequent changes to PostgreSQL in real time. MySQL types are mapped to Postgres equivalents automatically — TINYINT(1)→BOOLEAN, INT UNSIGNED→BIGINT, ENUM→TEXT, JSON→JSONB, DATETIME→TIMESTAMPTZ. Schema changes (ALTER TABLE) are applied and recorded; only a dropped table waits for your review. Works with MySQL 5.7+, Amazon RDS, Aurora and Cloud SQL.

  • Continuous replication via binlog ROW-format CDC after an initial snapshot
  • GTID and file+position replication both supported
  • Auto type mapping — TINYINT(1)→BOOLEAN, UNSIGNED→BIGINT, ENUM→TEXT
  • Schema changes (ALTER TABLE) detected, applied and recorded
How it works

How to replicate MySQL to PostgreSQL — 5 steps

From binlog setup to CDC streaming — typically under 10 minutes. Once the data lands, query it in the SQL Explorer or with Ask rsync.ai, shape it with Models, and publish Charts and Dashboards.

  1. 1

    Enable MySQL binlog

    Set `binlog_format=ROW` and `log_bin=ON` in your MySQL config (my.cnf / my.ini). Create a dedicated replication user: `CREATE USER 'rsync_cdc'@'%' IDENTIFIED BY '…'; GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'rsync_cdc'@'%';`. On Amazon RDS or Aurora, enable automated backups — that activates binlog automatically. Set the `binlog_format` parameter to ROW in your parameter group.

    binlog_format=ROW · log_bin=ON · REPLICATION SLAVE + REPLICATION CLIENT
  2. 2

    Connect MySQL source

    Provide your MySQL host, port (default 3306), replication username, password, and database name. rsync.ai connects as a replica, reads the current binlog position (or GTID set), and begins the initial snapshot of all selected tables. SSL/TLS and SSH tunnels are supported for databases inside a private VPC.

    mysql://rsync_cdc:pass@host:3306/mydb
  3. 3

    Connect PostgreSQL destination

    Provide your PostgreSQL host, port (default 5432), user, password, and target database. The user needs CREATE TABLE and INSERT/UPDATE/DELETE privileges on the target schema. rsync.ai will create the schema and tables for you if they don't already exist.

    postgres://user:pass@host:5432/analytics
  4. 4

    Describe the sync in plain English

    Tell rsync.ai what you want: 'Replicate all tables from MySQL mydb to PostgreSQL in real time.' The AI pipeline planner reads your MySQL schema, maps each table and column to Postgres equivalents, and proposes DDL for you to review. You can refine with follow-up instructions — 'exclude the sessions table' or 'hash the users.email column'.

    No SQL · No YAML · No DAGs
  5. 5

    Select tables, approve DDL, CDC starts

    rsync.ai shows each MySQL table with its proposed Postgres DDL and type mappings. Tick the tables you want, review any mapping decisions (UNSIGNED INT → BIGINT, TINYINT(1) → BOOLEAN, ENUM → TEXT with a CHECK constraint), then approve. rsync.ai takes a consistent snapshot, applies it to Postgres, then switches to streaming binlog events.

    Snapshot → streaming CDC

MySQL → PostgreSQL type mapping

rsync.ai proposes these mappings automatically. You review and approve every mapping before any data moves.

MySQL columnPostgreSQL columnNotes
users (INT UNSIGNED id, VARCHAR email, TINYINT(1) active)users (BIGINT id, TEXT email, BOOLEAN active)INT UNSIGNED → BIGINT prevents overflow. TINYINT(1) → BOOLEAN maps 0/1 to false/true.
orders (INT id, DECIMAL(10,2) total, DATETIME created_at)orders (INT id, NUMERIC(10,2) total, TIMESTAMPTZ created_at)DECIMAL → NUMERIC (exact semantics preserved). DATETIME → TIMESTAMPTZ with UTC normalisation.
products (INT id, TEXT description, JSON metadata)products (INT id, TEXT description, JSONB metadata)MySQL JSON → Postgres JSONB. JSONB allows indexing and operator queries.
sessions (VARCHAR(36) id, ENUM('active','expired') status)sessions (VARCHAR(36) id, TEXT status)MySQL ENUM → TEXT with a CHECK constraint enforcing the same allowed values.
transactions (BIGINT id, DECIMAL(18,8) amount, DATETIME ts)transactions (BIGINT id, NUMERIC(18,8) amount, TIMESTAMPTZ ts)High-precision DECIMAL preserved as NUMERIC. Sub-second timestamps retained via TIMESTAMPTZ.
audit_log (BIGINT id, VARCHAR(255) action, TEXT payload, DATETIME logged_at)audit_log (BIGINT id, VARCHAR(255) action, TEXT payload, TIMESTAMPTZ logged_at)High-volume append-only table. rsync.ai applies INSERTs only — no UPDATEs or DELETEs expected.

rsync.ai vs. Fivetran, Airbyte, AWS DMS for MySQL → PostgreSQL

Honest trade-offs for real-time MySQL to Postgres replication.

Featurersync.aiyouFivetranAirbyteAWS DMS
Real-time MySQL binlog CDC
Plain-English pipeline setup
Auto MySQL → Postgres type mapping
DDL change propagation (ALTER TABLE)
Self-host in your own VPC
Source-available connector code
No per-row / per-MAR pricing
Column-level PII masking

MySQL to PostgreSQL — frequently asked

How much latency does MySQL → PostgreSQL CDC introduce?

After the initial snapshot, rsync.ai streams MySQL changes to PostgreSQL continuously. Lag depends on transaction volume and the network distance between MySQL, rsync.ai and PostgreSQL. The initial snapshot takes longer — proportional to the table size — but CDC streaming starts in parallel as soon as the snapshot is complete, so the pipeline is never fully idle.

How does rsync.ai handle MySQL TINYINT(1) and UNSIGNED integers in PostgreSQL?

MySQL's TINYINT(1) is conventionally used as a boolean (0/1). rsync.ai maps it to PostgreSQL BOOLEAN automatically. MySQL's unsigned integer types (TINYINT UNSIGNED, SMALLINT UNSIGNED, INT UNSIGNED, BIGINT UNSIGNED) are promoted to the next larger signed Postgres type — SMALLINT, INT, BIGINT, and NUMERIC respectively — to prevent overflow. You can override any mapping in the DDL review step.

How are MySQL ENUMs handled in PostgreSQL?

MySQL ENUM columns are mapped to TEXT in PostgreSQL with a CHECK constraint that enforces the same set of allowed values (e.g. `CHECK (status IN ('active','inactive','pending'))`). Postgres native ENUM types are intentionally avoided because they require an ALTER TYPE to add values, which can block production traffic. The TEXT + CHECK approach is schema-compatible with MySQL and alters safely with ALTER TABLE … ADD CHECK.

Does rsync.ai require a primary key on every MySQL table?

A primary key (or unique not-null key) is strongly recommended — without one, rsync.ai cannot perform row-level upserts and must apply CDC events in order, which reduces throughput. For tables without a primary key rsync.ai falls back to INSERT-only mode (useful for append-only audit logs). You'll see a warning during the DDL review step for any table without a usable key.

What happens if MySQL restarts while rsync.ai is running?

rsync.ai persists the last acknowledged binlog position (or GTID set) to its control plane database after each batch of events is committed to PostgreSQL. When MySQL restarts, rsync.ai reconnects and resumes from that saved position — no events are lost and no rows are duplicated. If MySQL has rotated past the saved position (binlog purged), rsync.ai detects the gap and re-snapshots the affected tables automatically.

Can rsync.ai handle MySQL schema changes (ALTER TABLE) automatically?

Mostly, yes. rsync.ai detects schema changes on the MySQL tables it replicates. New columns and column type changes are applied to PostgreSQL and recorded in the pipeline's history. A dropped column stays in PostgreSQL, and the change is recorded. Only a dropped table waits for a person to decide what happens next.

Can I redact or mask PII columns before they reach PostgreSQL?

Yes. In the pipeline configuration you can mark any column as: Null (value replaced with NULL), Hashed (SHA-256 of the original value — consistent for joins, unreadable as plaintext), or Truncated (for strings, only the first N characters). Masking is applied in rsync.ai's processing layer before the write, so the raw value is not written to PostgreSQL.

How does rsync.ai compare to AWS DMS for MySQL → PostgreSQL?

AWS DMS is a managed AWS service for database migration and replication. rsync.ai differs in setup and visibility: you describe the pipeline in plain English and review every type-mapping decision in the DDL step before data moves. rsync.ai is live today on rsync.ai Cloud, and you can also self-host it: the code is source-available under the rsync.ai Source-Available License, so you can read and patch it.

Run your first MySQL to PostgreSQL pipeline free

The first 10 GB of data moved is free. Describe the sync in plain English and review the plan before anything runs.

Start free