A domain change sounds like one setting. It isn’t — WordPress writes its address into thousands of database rows, some of them serialized in a way that breaks if you edit it with a plain find-and-replace. The fix is letting WP-CLI do the replacing, because it understands serialized data and a text editor doesn’t. You’ll need WP-CLI, SSH access, and control of both domains’ DNS.
Take the backup first
One database export with a name that explains itself:
wp db export ../backups/pre-domain-move-$(date +%Y-%m-%d).sql
If that command feels unfamiliar, do the backup lesson first — a domain move is exactly the kind of trip you want a way back from.
Point the new domain at the site
In your host’s panel, add the new domain to the site (usually “add domain”
or “alias”), then point the new domain’s DNS at the same server the old one
uses. Get an SSL certificate issued for the new name before you switch —
most hosts do Let’s Encrypt automatically once DNS resolves. Don’t run the
search-replace until https://newdomain.com loads something, even if
it’s the site wearing the old name.
Run the dry run
This shows every change without making any:
wp search-replace 'https://olddomain.com' 'https://newdomain.com' \
--dry-run --all-tables-with-prefix --skip-columns=guid
--all-tables-with-prefix catches plugin tables (WooCommerce, Yoast) that
plain mode skips. --skip-columns=guid leaves post GUIDs alone — they’re
permanent IDs, not links, and changing them re-sends your whole RSS feed.
Read the table of counts it prints. If a number surprises you, look before
you leap.
Run it for real
Same command, no --dry-run. Then repeat for the variants that hide in
old content — http:// and www:
wp search-replace 'https://olddomain.com' 'https://newdomain.com' --all-tables-with-prefix --skip-columns=guid
wp search-replace 'http://olddomain.com' 'https://newdomain.com' --all-tables-with-prefix --skip-columns=guid
wp search-replace '//www.olddomain.com' '//newdomain.com' --all-tables-with-prefix --skip-columns=guid
wp cache flush
This updates siteurl and home too, so there’s no separate settings
step. If WP_HOME or WP_SITEURL are hardcoded in wp-config.php,
update those by hand — they override the database.
Redirect the old domain permanently
Keep the old domain registered and 301 everything to its new address, path
included, so bookmarks and years of Google links still land. If your host
has a redirect feature, use it. On Apache, this in the old domain’s
.htaccess does the job:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]
Hold onto the old domain for at least a year — ideally forever. A lapsed domain that once had traffic gets scooped up fast, and you don’t want your old name pointing at someone else’s casino.
Verify the move stuck
Click through the site on the new domain: front page, a few posts, and the
media library — images are where a half-done replace shows first. Log in at
https://newdomain.com/wp-login.php. Then visit a deep URL on the old
domain and confirm it 301s to the same path on the new one (curl shows it
plainly):
curl -sI https://olddomain.com/some-old-post/ | grep -i 'location\|HTTP'
Finally, view source on a page and search for the old domain — zero matches means the move is done, not half-moved. If anything’s wrong, that backup from step one restores in minutes.