From Supabase
Tested with: Supabase preset: offline fixtures (URL detection, rewrites, checklist) · sync/cutover end-to-end on PostgreSQL 17 · zb migrate 0.1
Every Supabase project has a PostgreSQL database. Databasezy copies your own schemas and data into a PostgreSQL instance; Supabase’s platform services stay behind.
| Status | Available |
|---|---|
| Target engines | PostgreSQL |
| How we read it | Connection string |
| Continuous sync | Yes, for PostgreSQL |
| Provider preset | supabase |
Before you start
Section titled “Before you start”- A Databasezy PostgreSQL instance, or use
--create. - The database password for the
postgresrole. - A plan for replacing Supabase Auth, Storage and Realtime in your application if you use them.
Find the connection string
Section titled “Find the connection string”Open the project, choose Connect (or project settings, Database) and copy a connection string. The preset handles all three kinds:
- Direct (
db.<ref>.supabase.co:5432): used as is. - Transaction pooler (
*.pooler.supabase.com:6543): rewritten to the direct host, and the userpostgres.<ref>becomespostgres, because transaction mode cannot servepg_dump. - Session pooler (
*.pooler.supabase.com:5432): kept for a plain copy, rewritten to the direct host for sync.
The direct host is IPv6-only unless the project has the IPv4 add-on. If the migration cannot connect, enable the add-on or use the session pooler with a plain copy.
Supabase notes
Section titled “Supabase notes”- Use the direct connection (port 5432), not the transaction pooler (port 6543).
- The auth, storage and realtime schemas are Supabase services; they are skipped by default.
- Extensions we do not ship are listed in the preflight report.
Platform schemas are skipped unless you pass --include: auth, storage, realtime, supabase_functions,
supabase_migrations, vault, graphql, graphql_public, extensions, pgsodium, net and cron. Row-level
security policies on your own tables are restored with them.
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 Supabase; 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 "postgresql://postgres.abcdefgh:[email protected]:6543/postgres" --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 "postgresql://postgres.abcdefgh:[email protected]:6543/postgres" --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": "postgresql://postgres.abcdefgh:[email protected]:6543/postgres", "provider": "supabase" }, "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"wal_level is already logical on Supabase. Preflight checks that the postgres role may replicate and lists
tables without a primary key.
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.
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”Preflight cannot reach db.<ref>.supabase.co
Section titled “Preflight cannot reach db.<ref>.supabase.co”The direct host has only an IPv6 address on projects without the IPv4 add-on. Enable the add-on, or use the session pooler for a copy without sync.
The restore stops on a Supabase extension
Section titled “The restore stops on a Supabase extension”pg_graphql, pgsodium, supabase_vault and pg_net live in excluded schemas. If one of your tables depends on them, remove the dependency or exclude that table.
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.
For anything else, zb migrate status <mig_id> shows the failing step and its message. How migrations work describes every step.