MySQL to PostgreSQL
Most people moving MySQL to PostgreSQL want a one-time migration, and for that a migration tool is the right choice. If you need PostgreSQL to stay in step with a MySQL database that keeps running, Weld replicates the tables you pick with binlog CDC or scheduled incremental syncs.
Checked against Weld and vendor docs on
Your own tables, picked when you set up the sync.
- Extract
- Load
- Keep in sync
- mysql.Synced
- mysql.Syncing
- mysql.Synced
- mysql.Synced
Trusted by data and AI teams
Three ways to get MySQL data into PostgreSQL
Start with the question of whether MySQL keeps running afterwards. A cutover migration wants schema, indexes and foreign keys moved once. Ongoing replication wants changes, including deletes, applied on a schedule or continuously.
pgloader
- Best for
- A one-time migration, schema included
- Effort
- Low to medium: one command or a load file, plus cast rules
- Freshness
- A single load run
- Good to know
- Creates tables, indexes and foreign keys by default and can reset sequences after loading. Its default casts turn tinyint(1) into boolean and zero dates into null. Its docs describe a load, not ongoing sync.
AWS Database Migration Service
- Best for
- Migrations with a cutover window on AWS
- Effort
- Medium: replication instance, endpoints, tasks
- Freshness
- Full load, then ongoing replication
- Good to know
- Creates tables and primary keys; other indexes and objects come from DMS Schema Conversion or AWS SCT. CDC needs row-based binlogs. Pay as you go for the replication resources.
Weld
- Best for
- Keeping PostgreSQL in sync with a live MySQL database
- Effort
- Low: connect both, pick tables, choose a sync mode
- Freshness
- Binlog CDC, or incremental syncs on your schedule
- Good to know
- Replicates table data rather than migrating indexes, triggers or views. CDC streams inserts, updates and deletes from the binlog; merge syncs need a primary key and an updated_at cursor.
How to sync MySQL to PostgreSQL with Weld.
In the app, with the API or an agent.
What lands in PostgreSQL
From MySQL to PostgreSQL.
A database has no fixed set of tables to list: what lands in PostgreSQL is your own tables, one destination table per source table you select, with a few columns Weld adds.
- Your selected tables
Each table you pick lands with its columns, minus any you removed and with any you chose to hash. Tables are added or changed later in the sync's configuration.
- _weld_synced
A timestamp Weld adds to every row with the time it was synced. Use it to check freshness and to build incremental models downstream.
- Tables on CDC
Kept current from the binlog, deletes included. Only tables with a primary key or unique index that the Weld user can see are offered for CDC.
- Tables on incremental merge
Updated from rows whose cursor, ideally updated_at, moved since the last run. Deleted rows stay until a full sync removes them.
Is each replicated table current?
In PostgreSQL SQL.
Runs in PostgreSQL, assuming you named the destination schema mysql. Replace orders and customers with your own tables. _weld_synced is added by Weld; compare row_count with a count(*) on the MySQL side.
1select 'orders' as source_table,2 count(*) as row_count,3 max(_weld_synced) as last_synced4from mysql."orders"5union all6select 'customers',7 count(*),8 max(_weld_synced)9from mysql."customers"10order by last_syncedAsk your agent.
It queries PostgreSQL for you.
Connect Claude, Cursor, ChatGPT or your own agent to Weld over MCP. It reads the MySQL context, finds the tables it needs and runs the query in PostgreSQL.
Which MySQL tables do we have in PostgreSQL, and which is the largest?
Looking up what Weld has synced from MySQL.
Things to know.
Before you sync MySQL.
- CDC needs row-based binlogs and enough retention
- log_bin must be ON, binlog_format ROW, binlog_row_image FULL and server_id set. Weld will not offer CDC with less than 6 hours of binlog retention and recommends at least 3 days, so a sync that breaks over a weekend can resume without a full resync.
- Incremental syncs do not see deletes
- Merge and append modes miss rows deleted in MySQL. Either schedule a full sync at midnight on tables where deletes matter, or use CDC, which reads deletes from the binlog.
- Merge needs a key and a cursor
- Incremental merge needs a primary key and a cursor timestamp, preferably updated_at. Without an updated_at column, append mode adds new rows but does not capture updates to old ones.
- Server timezones must be IANA names
- If MySQL runs with a legacy or OS-specific timezone name, CDC may misread timestamps. Set the server to the IANA equivalent or choose the IANA timezone in the connector settings.
- RDS and Aurora set binlogs through parameter groups
- On Amazon RDS or Aurora MySQL, set binlog_format to ROW in a parameter group, restart, and raise binlog retention with mysql.rds_set_configuration, where 7 days is the maximum.
Keep reading.
Guides, docs and schema.
Common questions.
About MySQL to PostgreSQL.
Start syncing MySQL to PostgreSQL.
Set up your MySQL data pipeline in minutes. No credit card required. Free for 14 days.