Zero-Downtime Database Migrations: A Survival Guide for Norwegian Systems
I still remember the sweat running down my back during a migration for a major Oslo-based fintech back in 2019. We were moving 4TB of transaction data. The plan was solid. The scripts were tested. But we underestimated one thing: the target server's disk I/O steal time. The replication lag grew faster than the data transfer. We barely made the maintenance window.
Database migrations are surgery. You don't just hack away; you plan, you anesthetize, and you execute with precision. If you are reading this, you probably need to move a critical workload—maybe from a restrictive shared host or a dedicated server that's aging out—to a more flexible environment.
This guide isn't about "digital transformation" fluff. It's about moving bits from A to B without dropping connections, keeping the Datatilsynet (Norwegian Data Protection Authority) happy, and ensuring your new home has the IOPS to handle the load.
The Norwegian Context: Latency and Law
Before touching a single config file, look at the map. If your customers are in Bergen or Trondheim, hosting your database in Frankfurt or Amsterdam adds 20-30ms of round-trip latency. For a chatty application making 50 queries per page load, that's a full second of added delay. It kills user experience.
Furthermore, post-Schrems II, data sovereignty is not a buzzword; it's a legal minefield. Keeping your data on Norwegian soil—or at least within the EEA with strict safeguards—is mandatory for many sectors.
Pro Tip: When choosing a VPS, ping the gateway IP. From Oslo, a good local provider should give you sub-5ms latency. CoolVDS nodes in Oslo peer directly at NIX (Norwegian Internet Exchange), often delivering <2ms to major local ISPs.
The Strategy: Replication, Not Export
The "Dump and Restore" method (`pg_dump` or `mysqldump`) is dead for anything over 10GB. The downtime required to export, transfer, and import is unacceptable in 2024. The only professional path is Replication.
Step 1: The Pre-Flight Check
You need to verify that your source and destination speak the same language and that the network pipe is fat enough. Don't use standard `scp`. It's too slow due to encryption overhead on weak CPUs.
Check your link speed between servers:
iperf3 -c target_server_ip -p 5201
If you aren't getting near line speed (1Gbps or 10Gbps), check your MTU settings. A mismatch (1500 vs 9000 jumbo frames) will cause fragmentation and ruin throughput.
Step 2: Configuring the Source (PostgreSQL 16 Example)
Let's assume you are running PostgreSQL 16 on Ubuntu 24.04 LTS. You need to enable logical replication or streaming replication. For a full migration, Streaming Replication is usually faster and more robust.
Edit your `postgresql.conf` on the source:
listen_addresses = '*'
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
# Critical for performance during sync
wal_sender_timeout = 60s
And update `pg_hba.conf` to allow the new CoolVDS server to connect:
# Allow replication connections from the new server IP
host replication replicator 192.168.1.50/32 scram-sha-256
Reload configuration (don't restart yet if you can avoid it):
systemctl reload postgresql
Step 3: The Base Backup
On your CoolVDS target server, stop the database service and clear the data directory. Then, pull the base backup. This is where disk speed matters. If your VPS provider throttles your write speed to 100MB/s, this will take forever.
At CoolVDS, our NVMe storage arrays typically sustain extremely high write speeds, meaning the network is usually the only bottleneck.
# Run this on the NEW server (The Replica)
systemctl stop postgresql
rm -rf /var/lib/postgresql/16/main/*
# Pull the data
pg_basebackup -h source_ip -D /var/lib/postgresql/16/main -U replicator -P -v -X stream -C -S migration_slot
Flags explained:
-X stream: Streams WAL files while the backup is happening. Crucial so you don't fall behind.-C: Creates a replication slot automatically.-P: Shows progress.
Step 4: The Catch-Up Phase
Once the base backup finishes, you need to tell the new server it's a standby. Create a `standby.signal` file in the data directory and configure connection details.
Edit `postgresql.conf` on the new server:
primary_conninfo = 'host=source_ip port=5432 user=replicator password=SECRET application_name=coolvds_replica'
promote_trigger_file = '/tmp/touch_me_to_promote'
Start the server:
systemctl start postgresql
Check the logs. You should see:
LOG: entering standby mode
LOG: redo starts at 0/1A000028
LOG: consistent recovery state reached
The Hardware Reality: Why IOPS Matter
Here is the part most tutorials skip. When you start replicating, your new server is doing two things: writing new data from the master AND performing read checks. If you are on a "budget" VPS, you are likely sharing a spinning HDD or a cheap SATA SSD with 50 other noisy neighbors.
If your disk latency spikes above 10ms, the replication lag will increase. You will never catch up. You will be stuck in a loop of "almost synced" forever.
We built CoolVDS on KVM with strict resource isolation specifically for this reason. We expose raw NVMe performance to the guest OS. When you run `fio` benchmarks on our instances, you see the difference:
fio --name=randwrite --ioengine=libaio --iodepth=1 --rw=randwrite --bs=4k --direct=1 --size=512M --numjobs=2 --runtime=60 --group_reporting
On standard cloud hosts, you might get 3000 IOPS. On a properly configured CoolVDS instance, you can expect significantly higher throughput, ensuring your database writes never queue up.
The Cutover
You are now running two identical databases. The old one is the primary; the CoolVDS instance is the hot standby. The lag should be near 0 bytes.
- Stop the Application: Put up a maintenance page.
- Verify Sync: Run `SELECT * FROM pg_stat_replication;` on the master. Ensure state is 'streaming' and lag is 0.
- Promote the Standby:
/usr/lib/postgresql/16/bin/pg_ctl promote -D /var/lib/postgresql/16/main - Switch DNS/IP: Point your application config to the CoolVDS IP.
- Start Application.
Conclusion
Database migration is 90% preparation and 10% execution. By using streaming replication, you minimize downtime to seconds. By choosing a host with local Norwegian presence and high-performance NVMe storage, you ensure the new home is better than the old one.
Don't let slow I/O kill your SEO or your migration. Spin up a test instance on CoolVDS today and benchmark the difference yourself.