Disclosure: we may earn a commission or referral reward from CloudCone, Contabo, DigitalOcean (account credit, not cash), Hostwinds, InterServer, RackNerd, VPSDime and Vultr if you sign up through our links. It does not change the price you pay. Every other provider pays us nothing. Prices in this guide are as of the date shown and may have changed; see the comparison pages for the latest checked prices.
Guides · BLOG
How to migrate a database between VPS providers in 2026
Some prices quoted in this guide are out of date. It is being rebuilt on our price index; for current prices use the comparison pages, which show when each price was checked.
Every provider migration eventually hits the database question: how do you move a live Postgres or MySQL from one VPS to another with as little downtime as possible? This guide covers the three cleanest patterns, from "5-minute downtime is fine" to "we can't be down at all."
Choose your downtime tolerance
- 5-15 minutes downtime is fine. Simple
pg_dump/mysqldumpand restore. - 1-2 minutes downtime. Rsync warm followed by final delta.
- Zero downtime. Logical replication.
Ranked by complexity: 1 easiest, 3 hardest.
Pattern 1: pg_dump / mysqldump + restore (5-15 minutes downtime)
The default. Works for any database size where the dump-and-restore fits in your downtime window.
Postgres
On the source VPS:
```bash
pg_dump -F c -Z 9 mydb > /tmp/mydb.dump
scp /tmp/mydb.dump deploy@new-vps:/tmp/
```
On the destination VPS:
```bash
Create the DB and user
sudo -u postgres createuser --pwprompt mydb_user
sudo -u postgres createdb -O mydb_user mydb
Restore
pg_restore -h localhost -U mydb_user -d mydb /tmp/mydb.dump
```
Cutover:
1. Put your app into maintenance mode (or accept the 5-15 min downtime).
2. Take the final pg_dump and copy over.
3. Restore on the new VPS.
4. Update app config to point at the new DB.
5. Switch DNS / update load balancer / whatever moves traffic.
Time-boxed at "size of DB + network transfer + restore time". A 5 GB Postgres over a 100 Mbps link + 30 min restore = about 45 minutes of downtime.
MySQL / MariaDB
Same shape:
```bash
mysqldump --single-transaction --routines --triggers mydb > /tmp/mydb.sql
scp /tmp/mydb.sql deploy@new-vps:/tmp/
```
On destination:
```bash
mysql < /tmp/mydb.sql
```
--single-transaction gives you a consistent snapshot on InnoDB without table locks.
Pattern 2: Rsync warm + final delta (1-2 minutes downtime)
For databases too big to dump-and-restore in your downtime window. Copies the database files while the source is live, then does a final delta after briefly stopping the source.
Works on Postgres via pg_basebackup (physical replication) or on any DB via a rsync of the data directory.
Postgres physical backup approach
On the source, take a base backup:
```bash
sudo -u postgres pg_basebackup -h localhost -D /tmp/pgbackup -F t -z
scp -r /tmp/pgbackup/* deploy@new-vps:/tmp/pgbackup/
```
On the destination:
```bash
sudo systemctl stop postgresql
sudo -u postgres tar -xzf /tmp/pgbackup/base.tar.gz -C /var/lib/postgresql/16/main/
sudo systemctl start postgresql
```
Cutover:
1. Stop the source (accept ~1 min downtime).
2. Take one more pg_dump of just the new data since the base backup.
3. Restore that delta on the destination.
4. Switch app to the new DB.
Total downtime: 1-2 minutes if you've done the base backup and restore ahead of time.
Pattern 3: Logical replication (zero downtime)
For real production databases where any downtime is unacceptable. Uses Postgres's built-in logical replication (or MySQL's binlog-based replication).
Postgres logical replication
On the destination, set up as a subscriber:
```sql
-- On both source and destination:
CREATE PUBLICATION mypub FOR ALL TABLES;
-- On destination:
CREATE SUBSCRIPTION mysub
CONNECTION 'host=source-ip dbname=mydb user=replica password=xxx'
PUBLICATION mypub;
```
The destination now replicates all changes from the source in real time.
Cutover:
1. Wait until the replication is fully caught up (check pg_replication_slots on the source).
2. Stop writes on the source (via app-level pause or briefly changing DNS).
3. Verify final catch-up.
4. Point app at the destination.
5. Drop the subscription on the destination.
Total downtime: seconds — the time between stopping the source and switching the app.
Downside: schema changes during migration are complex. If you can freeze DDL for the migration window, this is the cleanest path.
MySQL binlog replication
Same shape via MySQL replication. On the destination, CHANGE MASTER TO ... master_host='source-ip' and start replication. Cutover when caught up.
Common gotchas
Timezone handling. Postgres respects timezone per-cluster. Ensure both source and destination are configured the same.
Encoding. UTF-8 on both. Check with SHOW SERVER_ENCODING.
Extensions. If your DB uses postgis, hstore, pg_trgm, or others — install them on the destination BEFORE restore.
Sequence values. After pg_restore, sequences may be reset. If your IDs use sequences, verify they continue from the correct value.
MySQL character sets. utf8 vs utf8mb4 — always use utf8mb4 (the real 4-byte UTF-8).
Connection strings. Update your app's config on every environment (production, staging, background workers). Missed one = 500 errors from that instance.
Application connection pool. Existing connections stay open through the switch. Restart your app services after the cutover.
Downtime windows for reference
- Small database (< 500 MB): dump + restore in under 5 minutes. Pattern 1.
- Medium database (500 MB - 20 GB): dump + restore in 15-45 minutes. Pattern 1 or 2.
- Large database (20-500 GB): dump + restore in hours. Pattern 2 or 3.
- Any database over 500 GB or with zero-downtime requirement: Pattern 3 (logical replication).
Testing before cutover
Do a dry run. Restore to a temp DB. Point a staging environment at it. Verify data integrity.
Time the cutover. How long does the actual switch take? Rehearse it.
Have a rollback plan. If cutover fails, can you switch back to the source within 5 minutes?
Related guides
- DigitalOcean to Hetzner migration — includes DB migration for the DO Managed → self-hosted case.
- Best hosting for a Postgres database server — the target-side hosting picks.
- How to set up automated backups on any VPS — backup strategy that pairs with migration.
Prices as of 2026-09-22.