Skip to content
Tecno Blocks
Web Development11 min read589 words

Migrating 12 years of content without breaking a single URL

184,000 URLs, four historical URL schemes, and a CMS swap. The redirect map was the project; the migration was the footnote.

Tecno Blocks
Old street signs bolted to a brick wall, pointing in several directions
Old street signs bolted to a brick wall, pointing in several directions

Short answer

Treat the redirect map as the deliverable. We built it from 12 years of access logs before writing any migration code, tested it against 2.1 million real request paths, and shipped it behind the old domain first. Zero 404s from previously valid URLs; organic traffic dipped 4% for three weeks and recovered.

On this page
  1. The inventory
  2. Why does the redirect map come before the migration?
  3. Testing against reality
  4. Shipping in the wrong order, deliberately
  5. The numbers, twelve weeks on

Content migrations fail on URLs. The content itself is rows in a table; moving rows is a solved problem. What breaks is the 12 years of links that point at the old rows — from search engines, from other sites, from printed materials, from the bookmarks bar of a reader who has never seen your new design and does not care.

The inventory

We started with the access logs, not the database. Twelve months of logs gave us 2.1 million distinct request paths that had returned 200. We grouped them by pattern and found four URL schemes layered over the years.

  • /2014/03/slug — the original date-prefixed scheme, 31,000 URLs
  • /articles/slug — the 2017 flattening, 89,000 URLs
  • /a/12345 — numeric IDs from a 2020 app integration, 40,000 URLs
  • /p/slug?ref=... — a 2022 experiment nobody removed, 24,000 URLs

Every scheme was still receiving traffic. The 2014 date URLs alone got 1.4% of organic sessions.

Why does the redirect map come before the migration?

Because the migration is reversible and the redirect map is not. If the new CMS is wrong, you switch back. If Google recrawls 184,000 URLs and finds 404s, the rankings you lose take months to rebuild — the Google Search Central documentation on site moves is explicit that redirects must be in place before the move, not after.

So we built the map first, as a versioned file in its own repository, with tests.

// redirects.test.ts — every historical path must resolve to exactly one canonical URL
for (const path of historicalPaths) {
  const target = resolve(path);
  expect(target, path).toMatch(/^\/[a-z0-9-]+\/[a-z0-9-]+$/);
  expect(chainLength(path)).toBeLessThanOrEqual(1);
}

The chain-length assertion mattered. Two of the older schemes already redirected to each other; without it, a 2014 URL would have hopped three times before landing, and every hop costs crawl budget and a little link equity.

Testing against reality

The map was tested against all 2.1 million logged paths, not just the 184,000 canonical ones. That turned up 7,600 paths we had not modelled: trailing slashes, uppercase slugs from an old email tool, URL-encoded characters from a syndication partner. Each pattern got a rule. Sixty-one paths could not be resolved — mostly genuinely deleted content — and got a 410 rather than a 404, which tells crawlers to stop asking.

The migration tests passed on day one. The redirect tests took five weeks to pass. That ratio is the whole lesson.

Shipping in the wrong order, deliberately

  1. Deploy the redirect map on the old site, pointing to new-scheme URLs served by the old CMS. Watch for a week.
  2. Swap the CMS behind the same URLs. Watch for a week.
  3. Change the design.

Step one caught 214 broken redirects in production with the old system still fully in place to fall back to. Step two was a non-event. Step three generated complaints about the font, which is the correct kind of complaint.

The numbers, twelve weeks on

  • 404s from previously valid URLs: 0. We alert on any request path that appears in the historical set and returns 404.
  • Organic sessions: down 4.1% in weeks two to four, back to baseline by week seven, up 6% by week twelve as the canonical URLs consolidated.
  • Redirect chain length across the corpus: median 1, max 1.

The migration itself — the CMS swap — was 11 days of engineering. The redirect map was 5 weeks. Anyone who budgets those the other way round will find out why, about a month after launch.

Frequently asked questions

Why use 410 instead of 404 for deleted content?
A 410 tells crawlers the resource is gone on purpose. They stop retrying sooner and drop it from the index faster than a 404, which is treated as possibly temporary.
How long should redirects stay in place?
Indefinitely. They are cheap to serve and the long tail of inbound links never fully dies. We still see traffic on 2014-scheme URLs.
Did you change the URL scheme at all?
Yes — to /category/slug. But the redirect map was deployed weeks before the CMS moved, so the scheme change and the platform change were never live at the same time.

Sources

  1. Site moves with URL changesGoogle Search Central
  2. Cool URIs don't changeW3C

Published by

Tecno Blocks

Engineering insights from Tecno Blocks covering web, mobile, AI, Web3, software architecture, product development, DevOps, and real-world case studies.

About the publication

Related reading

Keep going