I have watched a company lose about 70 percent of organic traffic in eleven days because a redirect map was built from a sitemap that was already two years out of date. Every URL in the sitemap redirected perfectly. The 900 URLs that had been published since, including their three highest converting pages, all returned 404.
Nobody checked against logs. Nobody checked against Search Console. The map was built from the wrong source and the review passed because the sample they tested came from the same wrong source.
Migrations fail in boring, preventable ways. Here is the sequence I use.
Phase one: inventory, three weeks out
You cannot preserve what you have not counted. Build one master list of every URL, from four sources, deduplicated.
Your CMS export. Your XML sitemaps. Server log files for the last 90 days, which is the only source that tells you what crawlers actually request. And Search Console performance data for the last 16 months, which tells you what earns impressions.
That fourth source is the one that catches the disaster in my opening story. Log files are the one that catches URLs nobody remembers publishing.
For each URL record: current traffic, current impressions, backlinks pointing at it, conversions attributed to it, and whether it is templated or unique. This becomes your priority list, because you will not have time to hand check 4,000 redirects and you need to know which 200 matter.
Phase two: the redirect map
One row per old URL, one destination, no exceptions.
The rules I enforce:
301, always. Not 302, not a meta refresh, not a JavaScript redirect. Temporary redirects on a permanent move is one of the most common causes of a migration that half works.
No chains. Old URL to new URL, directly. If your site has previous migrations layered in, you will have chains of three or four hops. Flatten them to single hops against the final destination. Every hop loses something and some crawlers stop following after a few.
No mass redirects to the homepage. If a page has no equivalent, redirect to the closest relevant page. If there is genuinely nothing relevant, return a 410 and accept it. Redirecting a hundred deleted product pages to the homepage gets them treated as soft 404s anyway, and you have lost the ability to see what happened.
Test the map before launch. Take the top 200 URLs by value plus a random sample of 200 more and verify destination and status code on staging.
Phase three: parity checking
The question is not "did the pages move." It is "did the pages arrive intact."
For every major template, compare old and new on: title tag, meta description, H1, body word count, internal links out, structured data, canonical tag, image alt text, and hreflang if you have it.
The most common losses I find are body content that got trimmed by a designer who thought the page was too long, internal links that vanished because a related-posts module did not carry over, and structured data that disappeared with the old theme. Rebuild the schema deliberately rather than assuming the new platform handles it. My argument for what to actually implement is in structured data beyond the basics.
Internal linking deserves specific attention because it is invisible when it breaks. A new template that drops the contextual link module can silently strip thousands of internal links and collapse the link equity distribution described in internal linking architecture.
Phase four: the pre-launch gate
Nothing launches without every one of these confirmed.
Staging is blocked from indexing and the block is removed at launch. I have seen a live site launch with a noindex tag inherited from staging more than once, and it is a two week recovery.
Robots.txt on the new environment is the intended one, not the staging one. Write it by hand if you have to, and if the platform generated it for you, replace it with one you understand line by line.
Analytics and conversion tracking fire on the new templates, verified by an actual test conversion, not by assumption.
Canonical tags point at the new URLs on the new domain, absolute, not relative.
XML sitemaps regenerated with only the new URLs, with correct lastmod values.
Search Console property created and verified for the new domain before launch, not after.
Titles and descriptions render as intended at real pixel widths. A SERP snippet preview catches truncation on the ones that matter before they go live rather than after.
Phase five: launch day and the two weeks after
Launch at the lowest traffic point in your week, never on a Friday, and never before anyone takes leave.
Immediately after: submit the new sitemaps, use the change of address tool if the domain changed, and crawl the entire new site to catch anything that returns a non 200 status.
Then monitor daily for fourteen days: 404 volume in Search Console and logs, index coverage counts, crawl rate, and the ranking positions of your top 50 terms.
Expect volatility. A two to three week wobble is normal and is not a reason to start reverting things. What is not normal is a sustained decline past week four, or a 404 count that climbs rather than falls.
The single highest value activity in this window is reading 404 logs every morning and adding rows to the redirect map. Every migration produces URLs nobody anticipated, and the difference between a good and bad outcome is usually whether someone was watching for the first month.
The parts people skip and pay for
Backlink recovery. Your most linked pages should redirect to genuinely equivalent content, and for the top ten or so it is worth emailing the linking sites to update. Most will not. Some will, and those are your most valuable links.
Old assets. Images, PDFs, and downloadable files have URLs too, and they earn links and traffic. They are almost never in the redirect map.
Search operators and paginated URLs. Faceted navigation and paginated series produce enormous URL counts that need a deliberate decision, not an accident.
Performance regression. New platforms frequently ship heavier. Baseline your Core Web Vitals before launch and check them again after, using the priorities in Core Web Vitals in practice.
And if the migration is attached to a rebrand, the naming and identity work has its own failure modes, covered in the rebranding guide.
Keep the old site accessible for a week
One habit that has saved me repeatedly: keep the old site running on an internal address, crawlable by you but not the public, for at least a week after launch.
When someone says "the pricing page used to have a comparison table and now it does not," you can check in thirty seconds instead of digging through archives. When a URL turns up in the logs that is not in your map, you can see what it was.
It costs almost nothing and it converts the worst part of a migration, which is arguing about what used to exist, into a lookup. Every migration I have run without that safety net has involved at least one afternoon lost to reconstructing a page from memory, and memory is always wrong.