From Amazon RDS and Aurora
Tested with: RDS preset: offline fixtures (detection, checklist) · sync/cutover end-to-end on PostgreSQL 17 and MySQL 8.4 · zb migrate 0.1
RDS and Aurora run PostgreSQL, MySQL and MariaDB. Each moves to the matching Databasezy engine, with continuous sync for PostgreSQL and MySQL.
| Status | Coming soon · phase 2 |
|---|---|
| Target engines | PostgreSQL , MySQL , MariaDB |
| How we read it | Connection string |
| Continuous sync | Yes, for PostgreSQL and MySQL |
| Provider preset | rds |
Before you start
Section titled “Before you start”- A Databasezy instance of the same engine, or use
--create. - A database user with a password (not IAM authentication) and read access to everything you migrate.
- Network access from the migration egress addresses, or a machine inside the VPC for
--from local. - For continuous sync: a parameter group change and a reboot (see below).
Find the connection string
Section titled “Find the connection string”In the RDS console, open the instance (or the Aurora cluster) and copy the writer endpoint and port from Connectivity & security. Build the URL with your migration user’s password.
Amazon RDS and Aurora notes
Section titled “Amazon RDS and Aurora notes”- Add the migration egress IPs shown in the portal to the instance security group.
- Continuous sync needs rds.logical_replication=1 (Postgres) or binlog_format=ROW (MySQL) in the parameter group.
- Make the source reachable: enable Public access temporarily and add an inbound rule for the egress addresses to
the instance’s security group. Alternatively run
zb migrate --from localfrom a machine inside the VPC: it streams a dump and needs no inbound access, but cannot sync. - IAM authentication tokens expire after 15 minutes; the preset warns (
rds.iam_auth) when the URL has no password. - RDS Proxy endpoints are flagged (
rds.proxy_endpoint) and Aurora reader endpoints (cluster-ro-) block sync. - RDS-only extensions such as
pg_cron,aws_s3andaws_lambdaappear in the preflight report. - Heroku Postgres Essential and Standard databases also live under
rds.amazonaws.com; they are detected as Heroku.
Migrate
Section titled “Migrate”- Open the target PostgreSQL instance (create one first if you need to) and choose the Migrate in tab.
- Under Source, pick Connection string and paste the URL. The host is recognised as Amazon RDS and Aurora; you can also pick it from the provider list.
- Choose Copy and sync to keep the target current until cutover, or Copy for a one-off copy.
- Run Preflight and work through the checklist. Blocking items must be fixed before the copy starts.
- Start the copy and follow Copy and Verify. Mismatches are listed per table or collection.
- When the sync lag is low, stop writes and choose Cut over. The Report step keeps the timings and verification results.
# Dry run: print the preflight checklist and the plan, change nothingzb migrate --from "postgres://migrator:[email protected]:5432/app" --to inst_abc --mode copy_and_sync --dry-run
# Start it (or use --create --size s1 instead of --to to create the target)zb migrate --from "postgres://migrator:[email protected]:5432/app" --to inst_abc --mode copy_and_sync
zb migrate status mig_123zb migrate cutover mig_123 # when status says ready_for_cutovercurl -sS https://api.databasezy.com/v1/orgs/$ZB_ORG/instances/inst_abc/migrations \ -H "Authorization: Bearer $ZB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source": { "kind": "connection_string", "url": "postgres://migrator:[email protected]:5432/app", "provider": "rds" }, "mode": "copy_and_sync"}'
# Follow progress, preflight report and verificationcurl -sS https://api.databasezy.com/v1/orgs/$ZB_ORG/instances/inst_abc/migrations/mig_123 -H "Authorization: Bearer $ZB_API_KEY"
# Cut over once the status is ready_for_cutovercurl -sS -X POST https://api.databasezy.com/v1/orgs/$ZB_ORG/instances/inst_abc/migrations/mig_123/actions/cutover -H "Authorization: Bearer $ZB_API_KEY"PostgreSQL sync: set rds.logical_replication = 1 in the parameter group (Aurora: the cluster parameter group),
reboot, and grant rds_replication to the migration user. Preflight checks both (pg.wal_level,
replication.privilege).
MySQL: use the MySQL endpoint and target a MySQL instance:
--to inst_abc --mode copy_and_syncThe preset adds ssl-mode=REQUIRED. For sync, set binlog_format=ROW, gtid_mode=ON and
enforce_gtid_consistency=ON in the parameter group, keep binlogs for the whole sync
(CALL mysql.rds_set_configuration('binlog retention hours', 24)), and give the user REPLICATION SLAVE,
REPLICATION CLIENT and read access. The copy runs with --set-gtid-purged=ON so replication starts right after it.
MariaDB sources target the MariaDB engine, which is coming soon.
Verify
Section titled “Verify”Verification runs automatically after the copy and compares source and target: row counts per table, sequence or
AUTO_INCREMENT values, the number of indexes and a schema hash. A missing table or a short row count fails the
migration and lists what differs. Check the result with zb migrate status <mig_id> or the Verify step in the
portal, then run your application’s own smoke tests against the new instance before you switch traffic.
Continuous sync and cutover
Section titled “Continuous sync and cutover”With copy and sync, the target keeps receiving changes after the copy. When zb migrate status reports
ready_for_cutover (two lag samples in a row under 5 seconds):
- Stop writes to the source: maintenance mode, scale writers to zero, or revoke the application user.
- Run
zb migrate cutover <mig_id>(or Cut over in the portal). The agent drains the last changes, copies sequence values (PostgreSQL), verifies again and stops replication. If the target cannot catch up in time, the cutover is abandoned and sync keeps running; nothing changes on either side. - Point the application at the Databasezy connection string and resume writes.
zb migrate statusshows the measured downtime.
Schema changes are not replicated, so freeze migrations between the copy and cutover. Details: what happens at cutover.
Sync applies to PostgreSQL and MySQL targets only; other engines from this source are copy only.
Roll back
Section titled “Roll back”A migration never deletes anything on the source. Until you decommission it, rolling back means pointing the application back at the source.
- Before cutover: cancel with
zb migrate cancel <mig_id>. The publication, replication slot or replication channel the migration created is removed. - After cutover: writes made on Databasezy are not on the source. For PostgreSQL, start the migration with
--reverse-syncso the old database keeps receiving them after cutover and stays a valid fallback. Without it, copy the new data back with a migration in the other direction before you switch.
Troubleshooting
Section titled “Troubleshooting”The copy stops after about 15 minutes with an authentication error
Section titled “The copy stops after about 15 minutes with an authentication error”The URL used an IAM token. Create a password user for the migration.
Sync never becomes ready on Aurora
Section titled “Sync never becomes ready on Aurora”The URL points at the reader endpoint. Use the cluster writer endpoint.
Remove access after the migration
Section titled “Remove access after the migration”Delete the temporary security-group rule and turn public access off again once you have cut over.
Preflight cannot connect to the source
Section titled “Preflight cannot connect to the source”Check that the source accepts connections from the egress addresses preflight prints, that the host is the public one and that the password has not been rotated. zb migrate --dry-run shows the exact URL that will be used after any rewrites.
Preflight lists blocking items
Section titled “Preflight lists blocking items”Each item has a machine code and a fix. Nothing is written to the target until every blocking item is resolved; warnings do not block.
The restore stops on an extension
Section titled “The restore stops on an extension”The source uses an extension Databasezy does not ship. Drop it on the source if it is unused, or exclude the objects that depend on it with --exclude.
Sync is blocked with pg.wal_level or pg.replica_identity
Section titled “Sync is blocked with pg.wal_level or pg.replica_identity”Logical replication needs wal_level=logical on the source and a primary key (or REPLICA IDENTITY FULL) on every published table. Preflight lists the tables.
Sync is blocked on binlog or GTID settings
Section titled “Sync is blocked on binlog or GTID settings”Continuous sync needs binlog_format=ROW, gtid_mode=ON, enforce_gtid_consistency=ON and a user with REPLICATION SLAVE and REPLICATION CLIENT. Preflight names whichever is missing.
For anything else, zb migrate status <mig_id> shows the failing step and its message. How migrations work describes every step.