A well-executed migration costs two to six weeks of ranking turbulence; a botched one costs 20–40% of organic traffic and months of recovery. The difference is nearly always the redirect map: one-to-one, covering every URL that has traffic or backlinks, live from the first minute of cutover. Here is the checklist I run, in the order I run it.

The must-redirect list is the union of three exports:

  • A full crawl of the current site — sitemap URLs plus everything the link graph reaches, because the sitemap always lies a little.
  • Search Console performance data, all 16 months, pulled via the API (the UI export caps at 1,000 rows, which on any real site is a sample pretending to be a census).
  • Every URL with external backlinks — Search Console's "Top linked pages" report is the free source; a paid index adds coverage if you have one.

Anything in that union gets an explicit redirect. Everything else may die honestly. And freeze other variables now: do not migrate, redesign, and rewrite content in one launch. When traffic moves — and it will — you need to know which change moved it.

The redirect map: one-to-one or don't bother

Every old URL maps to its closest living equivalent. The blanket redirect-to-homepage is the classic self-inflicted wound — Google treats irrelevant redirects as soft 404s, and the equity you were trying to carry evaporates. If a page has no equivalent, let it return 410 honestly rather than faking a destination.

Mechanically, generate the config from a version-controlled CSV rather than hand-editing server config:

# generated from redirect-map.csv at build time — do not edit by hand
redir /apps/jellyfin /app/jellyfin/ permanent
redir /tags/media /category/media-server/ permanent
redir /compare/photoprism-vs-immich /compare/immich-vs-photoprism/ permanent

One hop, old URL directly to final URL. Googlebot abandons chains after about ten hops, but reliability decays from hop two, and chains breed during migrations because new redirects stack on old ones. While you're in there, rewrite canonical tags and internal links to point at final URLs too — canonicals aimed at redirects are the silent companion bug of every migration.

Cutover day, in order

Verify both properties in Search Console before you start (old and new, if hosts are changing). Then: new site live; redirects live and tested — not eyeballed, tested:

# every mapping must land exactly, first hop
while IFS=$'\t' read -r old new; do
  got=$(curl -s -o /dev/null -w '%{redirect_url}' "$old")
  [ "$got" = "$new" ] || echo "MISS  $old -> $got (wanted $new)"
done < redirect-map.tsv

Submit the new sitemap, and keep a temporary sitemap of the old URLs submitted as well — it prompts Google to recrawl them quickly and see the 301s, which measurably shortens the turbulence window. For a domain change, file the Change of Address in Search Console the same day. The full procedure is documented in Google's site move guidance; the steps people skip are the old-URL sitemap and the robots.txt check (a staging Disallow: / surviving to production remains the most expensive one-line file in SEO).

The 90 days after

WhenCheckWhereRed flag
Daily, weeks 1–2404 and soft-404 spikesGSC Pages report, server logsAny top-100 page 404ing
WeeklyOld URLs still indexedGSC on the old propertyCount not falling by week 4
WeeklyPositions on top 100 pagesGSC or rank tracker>20% decline persisting past week 6
MonthlyGooglebot hits on old URLsServer logsNo decay trend by month 3

Normal looks like this: a 10–20% dip beginning within days of cutover, bottoming in weeks two to four, recovered by week six or eight. Do not panic-change anything during the dip — mid-turbulence "fixes" reset the clock and destroy your ability to attribute. If you are still down more than 20% at day 60, the cause is almost always findable: missed URLs in the map (diff your inventory against redirect hits in the logs), a template regression that changed on-page content, or internal links still pointing through redirects.

One more pre-cutover check that catches template-level surprises: content parity. Render twenty representative old/new page pairs and diff the extracted text — not the HTML, the text. Migrations sold as "URL-only" have a habit of quietly dropping an FAQ block or a spec table during the replatform, and a page that lost a third of its content will shed rankings no redirect can save. Twenty minutes with a text extractor before launch beats three weeks of post-hoc archaeology in the SERPs.

Redirects are not temporary scaffolding. Google recommends holding them at least a year; backlinks live forever, so the real answer is indefinitely — keep the old domain registered and redirecting for as long as it earns, which for a domain with any link history is years.

What I'd do

Inventory from crawl + GSC API + backlinks, 30 days out. One-to-one map in version control, generated into server config, tested by script. Cutover with both sitemaps submitted and Change of Address filed. Then 90 days of the monitoring table, hands off the other variables, with per-template sitemap sharding giving you section-level indexation the whole way. Migrations don't lose rankings; missing redirects, chained redirects, and impatient mid-dip meddling lose rankings — and all three are choices.