Why Changing Your CMS Broke Links You Never Touched
On this page
- Why “preserved” URLs are not preserved
- The redirect-firing trap
- Diagnose at the response level
- Build the map and fire reliable redirects
- Why the layer you redirect at matters
- Recovery and priority
- Frequently Asked Questions
- My redirect plugin says all rules are active, so why do old URLs still 404?
- Should I redirect everything to the homepage to clear the 404s?
- Sources
- Related posts:
A platform migration changes URL structure in ways you did not plan, and that is why URLs you thought you preserved now return 404. Trailing-slash handling, default permalink and path patterns, and special-character encoding all differ between content management systems, so a migration that “kept the same structure” can still alter every URL on the site. Old URLs and the backlinks pointing at them break silently. Worse, a redirect plugin reporting that its rules are “active” does not mean those redirects actually fire, because the web server, the server type, or a caching layer can intercept the request before the rule ever runs. The deliverable is to verify the 301 fires at the HTTP-response level and to build reliable, ideally server-level, redirects from a complete map of old URLs.
This is the cross-platform migration case. It is distinct from deliberately removing a date segment on the same CMS, where redirects exist and the issue is re-evaluation, and from Google continuing to crawl pages you deleted long ago. Here the new URLs differ unintentionally and the redirects may not execute.
Why “preserved” URLs are not preserved
To Google, /path and /path/ are two different URLs. If the old platform served URLs without a trailing slash and the new one appends one by default (or the reverse), every URL changed even though the visible slug did not. That alone can break an entire site’s worth of links.
Platform defaults compound it. Drupal can expose node URLs like /node/123 alongside path aliases; WordPress builds permalinks from a configurable pattern such as /category/post-title/ with an optional category prefix. Moving between systems without explicitly reproducing the old pattern leaves the new URLs structurally different. Special-character and encoding handling adds a third axis: spaces, accented characters, and punctuation in slugs may be encoded differently, producing URLs that look the same to a human but resolve differently to a server. Any of these can change every URL while the migration checklist reports “structure preserved.”
The redirect-firing trap
The most expensive mistake is trusting the plugin UI. A redirect plugin can show its rules as active and enabled while those redirects still return 404 in practice, for reasons that live below the application layer.
The web server can intercept the request before the CMS loads. On nginx or Apache, if a location or rewrite rule matches the request first, the server resolves it (often to a 404 for a path that no longer maps to a file) before the application’s redirect plugin ever runs. A caching layer can serve a previously cached 404 ahead of the plugin. A plugin conflict can prevent the rule from registering at all. In every case the UI says “active” and the live URL says “not found.” Never accept the plugin’s report as proof; read the actual response.
Diagnose at the response level
Open an old URL in an incognito or private window with DevTools’ Network panel open, and read the real status code returned: 301 (correct), 404 (broken), or 500 (server error). Incognito avoids your warm cache and any logged-in redirect behavior masking the truth. Do this for several representative old URLs across different sections, because the breakage often varies by URL pattern.
Then test at scale. Run a list-mode crawl in a tool like Screaming Frog over the full set of old URLs and read the response codes in bulk, so you see which patterns 301 cleanly and which return 404. To assemble that list of old URLs, export from Search Console: the Performance report’s Pages tab gives you the URLs that earned traffic, and the Page Indexing report’s detail views give you the indexed inventory. Together those are the canonical record of what Google knew about and what you must not orphan.
Build the map and fire reliable redirects
Produce an old-to-new redirect map as a CSV, pairing each old URL with its equivalent on the new platform or, where there is no exact match, the closest live page. Never map an old URL to a 404, and avoid mapping everything to the homepage, which Google can treat as a soft 404 and which strands the user.
Implement the redirects at the most reliable layer available. Server-level rules in .htaccess (Apache) or the nginx config execute before the application, so they are not subject to plugin conflicts or cache interception. If your host blocks server configuration, implement the rules at the CDN layer, which sits in front of the origin and is similarly reliable. Use 301 for these permanent moves, since 301 is the correct signal that a URL has moved for good. If you must use a plugin, treat its rules as provisional until you have verified each one fires with a live response check.
Why the layer you redirect at matters
The reliability of a redirect depends on where in the request path it executes. A request to your old URL passes through several layers before anything renders: the CDN (if present), the web server, and then the application or CMS. A redirect rule fires at the first layer that matches the request. If the web server has a rule that resolves the path, or returns a 404 because no file maps to it, the request never reaches the CMS and your plugin’s rule is irrelevant. That is exactly why a plugin can report “active” while the live URL returns 404: the plugin lives in the application layer, which runs last, and something ahead of it already answered.
Putting the rule at the earliest reliable layer avoids the whole class of failure. A server-level rule in the Apache or nginx configuration executes before the application loads, so it is immune to plugin conflicts and to the application being slow or unavailable. A CDN-level rule sits even further forward and is the right choice when a managed host blocks you from editing server config. Plugin-based redirects are the least reliable option because they depend on the request reaching the application intact and on no other layer intercepting it first, which is precisely the condition migrations tend to break. If a plugin is your only option, verify every rule with a live response check rather than the plugin’s own status display.
Recovery and priority
The reassuring part: backlink equity is disconnected, not destroyed. The referring pages still link to your old URLs; once a 301 fires, Google follows it and the signals flow to the new target on subsequent crawls. Recovery is a matter of fixing the redirect and waiting for recrawl, not of re-earning the links.
Sequence the work by value. Fix the highest-traffic and highest-backlink old URLs first, since those carry the most equity and the most lost sessions, then work down the list. Re-crawl after deploying to confirm the 404s have turned into 301s and that none of the targets themselves 404.
Frequently Asked Questions
My redirect plugin says all rules are active, so why do old URLs still 404?
Because the plugin UI reports its own state, not what the server actually returns. The web server (nginx or Apache) can resolve the request before the CMS loads, a caching layer can serve a cached 404 first, or a plugin conflict can stop the rule registering. Verify by requesting the old URL in incognito with DevTools open and reading the real status code.
Should I redirect everything to the homepage to clear the 404s?
No. Mapping many unrelated old URLs to the homepage tends to be treated as a soft 404 and gives users nothing relevant. Map each old URL to its true equivalent or the closest relevant live page, and only fall back to a section page, never a blanket homepage redirect.
Sources
Google Search Central, “Redirects and Google Search”: https://developers.google.com/search/docs/crawling-indexing/301-redirects
Google Search Central, “Site moves with URL changes”: https://developers.google.com/search/docs/crawling-indexing/site-move-with-url-changes