All postsTUTORIAL · 9 MIN READ

Moving WordPress to a new host with zero downtime.

TL
Tomas Linnamäki · Platform Engineer
·
May 3, 2026
0ms
DOWNTIME WHEN YOU DO IT RIGHT

The "easy" way to migrate WordPress is to put up a maintenance page, dump the database, copy files, and pray DNS propagates before customers notice. The "right" way is to keep both copies of the site running side by side until you're certain the new one is healthy, and only then flip the switch. Done well, your visitors never see a single error.

I've moved a few hundred sites onto our cPanel platform. This is the playbook that works.

The mental model

A WordPress migration has three independent moving parts:

  1. Files — the wp-content/ directory plus wp-config.php and a few root files
  2. Database — usually a single MySQL DB with ~12 core tables plus whatever your plugins added
  3. DNS — the A / AAAA / CNAME records that tell the world which IP serves your domain

You can copy files and DB whenever you want with no user impact. Visitors keep hitting the old host. The risky moment is the DNS flip — and even that risk shrinks to zero if you do the staging dance below.

Step 1 — set up the new host without DNS

Create the WordPress install on the new host first, but do not change DNS yet. On Rivervo cPanel:

  1. Add the domain as an addon or in the primary slot
  2. Use the Softaculous installer in cPanel to deploy a fresh WordPress at the doc root
  3. Note the temporary hostname — typically something like yourdomain.com.5-9-109-61.cpanel.site
  4. Visit that hostname in a browser to confirm Apache is serving the install

You now have a working WordPress on the new host that nobody can find unless they know the temp URL.

Step 2 — copy the files

The fastest path is rsync over SSH from old host to new. If your old host doesn't allow SSH, fall back to scp from your laptop or use the Backup → Full Backup option on cPanel and import the resulting tarball.

# From your local machine, with SSH keys set up on both sides:
rsync -avz --delete \
  user@oldhost:/home/old/public_html/ \
  user@newhost:/home/new/public_html/

--delete removes anything on the destination that isn't in the source — important if you're re-running the rsync later to catch new uploads.

If the old host is slow, run the rsync first time without --delete to get a baseline copy, then again right before cutover with --delete to catch deltas. The second run is fast.

Skip transient directories that are just going to slow you down:

rsync -avz \
  --exclude='wp-content/cache/' \
  --exclude='wp-content/uploads/cache/' \
  --exclude='*.log' \
  user@oldhost:/home/old/public_html/ user@newhost:/home/new/public_html/

Step 3 — copy the database

Dump on the old host:

mysqldump -u olduser -p --single-transaction --quick --lock-tables=false \
  oldwp > wp_backup.sql

--single-transaction is the magic flag — it takes a consistent read snapshot without locking the tables, so the old site keeps working while the dump runs. --quick streams rows row-by-row instead of buffering the whole table, which keeps memory low for big DBs.

Move the dump to the new host (scp, rsync, or wget depending on what's available) and import:

mysql -u newuser -p newwp < wp_backup.sql

Edit wp-config.php on the new host to point at the new DB credentials. Don't forget the $table_prefix if it isn't wp_.

Step 4 — fix the URLs without breaking anything

WordPress stores its siteurl in the DB. If the old install used https://yourdomain.com and you're testing on yourdomain.com.5-9-109-61.cpanel.site, the test site will redirect to the old URL the moment you visit the homepage.

Two clean ways to handle this:

Option A — local hosts file override (recommended). Edit /etc/hosts on your laptop:

1.2.3.4   yourdomain.com www.yourdomain.com

(Replace 1.2.3.4 with the new server's IP from cPanel.) Now your laptop resolves yourdomain.com to the new server while the rest of the world still hits the old one. You can browse the new site at its real URL, log in to wp-admin, click around, run plugins — all without touching DNS.

This is the cleanest approach because no URL search-and-replace is needed in the database.

Option B — temporary URL rewrite. Add to wp-config.php on the new install:

define('WP_HOME',    'https://yourdomain.com.5-9-109-61.cpanel.site');
define('WP_SITEURL', 'https://yourdomain.com.5-9-109-61.cpanel.site');

This overrides the DB values without writing to the DB. When you remove these constants after cutover, WordPress falls back to the original URL. Cleaner than running wp search-replace and forgetting to undo it.

Step 5 — sanity-check the new install

Walk through every part of the site as a logged-in admin and as a logged-out visitor:

  • Homepage loads, no missing assets in the browser console
  • Permalinks: visit a few internal URLs — if they 404, go to Settings → Permalinks and click Save (no changes needed; this regenerates .htaccess)
  • Search works (a broken DB import often breaks search before anything else)
  • Admin login — log in fresh, not via cookie carry-over from the old site
  • Form submissions — fire a test contact form, comment, registration
  • Email — trigger a password reset, confirm the email arrives
  • Cron — check Tools → Site Health for failed schedule warnings
  • Caching plugin — flush its cache, then re-enable. Caches built on the old host's path layout often cause blank pages on the new one.
  • CDN — if you use one, point it at the new origin IP now (most CDNs let you change origin without touching customer DNS)

Anything that doesn't pass — fix it on the new host before cutover. After cutover the pressure is on.

Step 6 — lower DNS TTL the day before

The day before you plan to cut over, edit your DNS records and lower the TTL to 300 seconds (5 minutes) for the A/AAAA records pointing at the old host. Save the change.

The reason: browsers and resolvers cache DNS answers for the TTL value. If the existing TTL is 3600 (1 hour), some visitors will keep hitting the old server for up to an hour after you flip records. With TTL=300, the longest anyone is stuck on the old host is 5 minutes after cutover.

If you forget this step, the cutover still works — but for an hour or so some users see the old site and others see the new one. They each get a consistent experience, just different. Annoying for analytics, harmless for users.

Step 7 — final delta sync

This is the only moment that requires care. Ten minutes before the actual DNS flip:

  1. Re-run rsync to catch any uploads, comments, or settings changes that happened on the old site since your initial copy. With --delete, deletions also propagate.
  2. Re-dump the DB with mysqldump --single-transaction and re-import. This catches new posts, new orders if it's WooCommerce, new user signups.
  3. Don't accept new traffic to the old site after this point — for blogs and brochure sites this is fine since traffic is read-only. For e-commerce, put up a "site updates in progress, orders accepted in 5 minutes" banner via a small plugin or .htaccess rewrite.

For a low-traffic blog you can skip the banner. For an active store, even a 5-minute window of "no new orders" beats the chaos of split-brain (some orders on old DB, some on new).

Step 8 — flip DNS

Update the A / AAAA records to the new server's IP. Keep TTL at 300 for now.

Open a new browser tab and pull the records to confirm the change went out:

dig +short yourdomain.com @1.1.1.1
dig +short yourdomain.com @8.8.8.8

You want to see the new IP. If you still see the old one after a minute, the change hasn't propagated to that resolver yet — wait two more minutes and re-check.

Step 9 — verify in production, then walk away

Once dig shows the new IP from at least two public resolvers:

  1. Remove the /etc/hosts override on your laptop (so you're now hitting the real site like a regular visitor would)
  2. Open the site in incognito and reproduce the same checks from Step 5
  3. Log in to wp-admin from a fresh browser and submit a test post
  4. If WooCommerce: place a £1 test order end-to-end with a real payment method, confirm the order email lands, then refund it

If everything passes, raise the TTL back to 3600 or higher. Leave the old host running for 7 days. Don't cancel until you've watched the new one bear real traffic for a week. If something subtle breaks (a cron job that fires once a week, an external integration that's whitelisted by IP), you want a path back.

Common failures and how they look

"White screen of death" after cutover. Almost always a PHP version mismatch. The new host uses a newer PHP that's stricter about deprecated syntax in old plugins. Check wp-content/debug.log, downgrade PHP one minor version in cPanel, then upgrade plugins one at a time until you can upgrade PHP again.

Missing images, broken styles. Permalinks need re-saving (Settings → Permalinks → Save) or the rsync skipped a directory because of a permission error. Run rsync again with -v and watch the output — files marked as failed need a manual chown on the source.

Logged-in users keep getting logged out. Cookies are domain-bound. If you used Option B's WP_SITEURL constants, the cookies were set for the temp domain. After removing the constants, browsers still send cookies for the old domain — they just don't match. Have users clear their cookies or wait 24h for natural expiry.

Email stops sending. WordPress core uses PHP mail() by default, which is unreliable. If your old host had a working SMTP plugin configured, the credentials should have come over with the rsync. If not, install WP Mail SMTP and configure it with the new host's SMTP credentials (cPanel → Email → Configure Email Client gives you the values).

Search engine traffic plummets after cutover. Check robots.txt and the Search Engine Visibility checkbox in Settings → Reading. Some hosts auto-disable indexing on staging environments and don't re-enable it on the live one.

What you save by doing this properly

A typical WordPress migration done the lazy way takes 2-4 hours with the site down for 30-60 minutes of that. Done the way above, the site stays up the entire time and the visible "downtime window" shrinks to zero.

If you're moving onto our hosting and want us to do this for you, reach out — we run free migrations for new accounts and the engineer doing it follows roughly the same checklist.