Migrations go wrong in predictable ways: old URLs return 404, the new site launches with "Discourage search engines" still ticked, image links point at the old domain, or redirects chain three hops deep. Each of these can cost traffic for months.
The good news is that a careful migration usually loses nothing. Google is explicit that a site move with proper redirects keeps its signals. This is the plan I follow.
Know which kind of move it isLink to this section
| Move | URLs change? | Main risks |
|---|---|---|
| New host, same domain | No | Downtime, missing files, DNS caching |
| New domain (rebrand) | Yes, host part | Redirects, internal links, Search Console |
New URL structure (e.g. /2024/05/post/ → /blog/post/) |
Yes, path part | Redirect mapping, internal links |
| New platform (WordPress → headless, or the reverse) | Often | All of the above, plus templates and metadata parity |
The more that changes, the more the redirect map matters.
1. Inventory before you touch anythingLink to this section
- Export every indexable URL. Combine the XML sitemap, a crawl of the site and the top pages in Search Console's Performance report. Pages with backlinks matter too; your SEO tool's "top pages by links" list catches URLs that aren't in the sitemap.
- Benchmark. Note clicks, impressions and top queries for the last three months, so you can compare after launch.
- Record the essentials for key pages: title, meta description, canonical, H1. You'll check they survive.
- Back up files and database, and confirm the backup restores.
2. Move files and databaseLink to this section
The most dependable method is WP-CLI on both servers:
# Old server
wp db export site.sql
tar -czf wp-content.tgz wp-content
# New server (fresh WordPress core installed, wp-config.php configured)
wp db import site.sql
tar -xzf wp-content.tgzMigration plugins work too for small sites. For large media libraries, sync wp-content/uploads with rsync rather than squeezing it into one archive.
Before switching DNS, lower the DNS record's TTL to about five minutes a day in advance. Then test the new server by pointing your own computer at it with a hosts-file entry.
3. Search-replace the old URL safelyLink to this section
WordPress stores some values as serialized PHP arrays, in widget settings, page-builder data and options. A plain SQL REPLACE() corrupts them because string lengths change. WP-CLI's search-replace understands serialization:
# Preview first
wp search-replace 'https://old-domain.com' 'https://www.new-domain.com' \
--all-tables-with-prefix --precise --dry-run --report-changed-only
# Then run it
wp search-replace 'https://old-domain.com' 'https://www.new-domain.com' \
--all-tables-with-prefix --precise --report-changed-only
wp cache flushAlso replace the http:// and protocol-relative variants if the old site ever ran without HTTPS. Leave GUIDs alone with --skip-columns=guid if you want to follow the WordPress recommendation not to change post GUIDs.
4. Map and implement 301 redirectsLink to this section
Every old URL that changes needs a permanent redirect, in one hop, to its closest new equivalent. That means old page to new page, not everything to the homepage. Google treats mass redirects to the homepage like soft 404s.
For a domain change with identical paths, one rule does it.
Apache (.htaccess on the old domain):
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?old-domain\.com$ [NC]
RewriteRule ^(.*)$ https://www.new-domain.com/$1 [R=301,L]Nginx:
server {
listen 443 ssl;
server_name old-domain.com www.old-domain.com;
return 301 https://www.new-domain.com$request_uri;
}When paths change too, you need a list of individual redirects. Build it in a spreadsheet with an old URL column and a new URL column, then paste it into the redirect generator. It outputs ready-to-use .htaccess, Nginx or Next.js rules and flags chains and duplicates. Test tricky patterns in the regex tester first.
Keep redirects in place for at least a year, and ideally permanently. Backlinks and bookmarks to old URLs never fully disappear.
Special casesLink to this section
Changing the permalink structureLink to this section
Moving from dated URLs such as /2023/05/post-name/ to /blog/post-name/ changes every post URL. WordPress sometimes guesses the new URL for a 404, but don't rely on that. One pattern rule handles the whole set:
# Apache: /2023/05/post-name/ → /blog/post-name/
RedirectMatch 301 ^/\d{4}/\d{2}/([^/]+)/?$ https://www.example.com/blog/$1# Nginx
rewrite ^/\d{4}/\d{2}/([^/]+)/?$ /blog/$1 permanent;Test the pattern against a list of real old URLs in the regex tester before deploying it. A pattern that's too broad can catch pages it shouldn't.
Changing a single post's slugLink to this section
WordPress records the old slug (_wp_old_slug) and redirects it automatically, so editing one URL in the editor is safe. That only covers posts on the same site; it doesn't help after a domain or structure change.
HTTP to HTTPSLink to this section
Treat it as a migration: one 301 from every http:// URL to its https:// equivalent, an updated site URL in Settings → General, and a search-replace for hard-coded http:// links in content so pages don't load mixed content.
5. Launch-day checksLink to this section
Run these within an hour of switching DNS:
- Settings → Reading → "Discourage search engines" is unchecked, and
robots.txtdoesn't sayDisallow: /. https://loads with a valid certificate, andhttp://plus the non-preferredwww/non-wwwvariant redirect in one hop.- A sample of 20–50 old URLs from your inventory return 301 → 200, not 404 and not chains. A quick loop helps:
while read url; do
curl -s -o /dev/null -w "%{http_code} %{redirect_url} $url\n" "$url"
done < old-urls.txt- Canonical tags and
og:urluse the new domain. Check them in the page source, or regenerate tags with the meta tag generator if a template hard-codes them. - No mixed-content warnings in the browser console (images or scripts still on
http://or on the old domain). - Forms, checkout and transactional emails work. Email often breaks because of SPF/DKIM or SMTP settings tied to the old server.
A rollback planLink to this section
Decide before launch what would make you switch back, and make switching back cheap:
- Keep the old server running, untouched, for at least a week after DNS moves. With a low TTL, pointing DNS back takes minutes.
- Freeze content on the old site during the move window, or note every order, form entry and comment that arrives on either server so nothing is lost if you return.
- Write down the triggers. For example: checkout failing, error rates above normal, or key pages returning 404s that can't be fixed within an hour.
Most migrations never use the plan, but having it lets you launch calmly and fix small issues forward instead of panicking.
6. Tell GoogleLink to this section
- Verify the new domain in Search Console. A Domain property covers all subdomains and protocols.
- Submit the new XML sitemap.
- For a domain change, use the Change of Address tool in the old property. It requires the 301s to be live.
- Keep the old property verified to watch its traffic move across.
- Update the URL everywhere you control it: Google Business Profile, social profiles, ad campaigns, email signatures.
7. The weeks afterLink to this section
- Watch Pages → Not indexed in Search Console for spikes in "Not found (404)" and fix them with redirects.
- Compare clicks with your benchmark. Some fluctuation for a few weeks is normal; a steady decline is not, and usually traces back to missing redirects or a
noindexleft on. - Check that Core Web Vitals didn't regress on the new host. The Core Web Vitals guide explains what to look at.
When traffic drops after a moveLink to this section
A dip for a week or two is normal while Google recrawls. A steady decline usually has a technical cause. Check these in order:
- Indexing blocked.
noindexin the page source or anX-Robots-Tagheader, often copied from staging. - Wrong redirect type.
302instead of301, which tells Google the move is temporary. - Redirect chains. Internal links still point to old URLs, so every click goes through a redirect. Update links in content and menus to the final URLs.
- Canonicals on the old host. Hard-coded canonicals or
og:urlvalues in a theme or SEO plugin settings. - Missing pages. The Pages → Not found (404) report in Search Console lists old URLs that weren't mapped.
- Slower site. A cheaper host can push Core Web Vitals into "needs improvement". Compare before and after.
Migration checklistLink to this section
- ☐ URL inventory and traffic benchmark saved.
- ☐ Backups verified; DNS TTL lowered a day ahead.
- ☐ Serialization-safe search-replace done; caches flushed.
- ☐ One-hop 301s for every changed URL; none to the homepage by default.
- ☐ Indexing allowed; canonicals point at the new URLs.
- ☐ HTTPS and host variants redirect correctly.
- ☐ Search Console: new property, sitemap, Change of Address.
- ☐ Redirects kept for at least a year.
Frequently asked questionsLink to this section
How long does it take for rankings to settle?Link to this section
Google says a medium-sized site can take a few weeks for most pages to move across, and larger sites longer. With clean redirects, the new URLs usually inherit their rankings without a lasting drop.
Should I keep the old domain?Link to this section
Yes. Keep renewing it. The redirects only work while the old domain resolves, and backlinks to it keep sending visitors and signals for years.
301 or 308?Link to this section
Both are permanent and Google treats them the same way. Use whichever your server or framework produces; Next.js uses 308 for permanent redirects.
Do I need to update internal links if redirects are in place?Link to this section
Yes. Redirects protect external links and bookmarks. Your own links should point straight at the final URL, which saves a hop for visitors and crawlers. A serialization-safe search-replace updates most of them in one pass.
If something did break after a move, the critical-error guide covers the common post-migration failures, and the technical SEO checklist helps you audit the new site. Planning a move? Send me the old and new setup and I'll map the risks.
Test yourself
3 quick questions on this lesson.
Finished this lesson?
Mark it complete to track your progress through the learning paths.