Migration assurance
Proving a content migration lost nothing
Moving a site between content platforms is easy to do and hard to prove. I built the test suite that checks the pages, the metadata and the content against a source of truth — and reports every failure as data.
- Availability, then metadata, then content — a failure upstream stops the noise downstream
- 3 dependent suitesAvailability, then metadata, then content — a failure upstream stops the noise downstream
- Retries only for specific network conditions, so flakiness cannot hide a real defect
- 0 blanket retriesRetries only for specific network conditions, so flakiness cannot hide a real defect
- Every failure emitted as a structured record, not a screenshot
- Failures as dataEvery failure emitted as a structured record, not a screenshot
The client
A large web estate migrating from one content management platform to another, staged behind a content delivery network, where the risk is not that the site breaks but that it quietly loses pages, metadata and search visibility.
The engagement
An automated verification suite in three dependent stages, run against staging before anyone signed off the migration.
The problem
A platform migration produces a site that loads. That is the trap. What actually goes missing is unglamorous and expensive: a canonical link, a meta description, an alt attribute, a legacy URL that no longer maps, a component that renders empty because its content did not come across. None of it is visible to someone clicking around, and all of it is visible to a search engine within weeks.
What I did
I made the suite argue with the migration rather than confirm it. Expected content and URL mappings live in a declared source-of-truth file, so tests compare against a stated intent instead of against whatever the new site happens to contain. The three stages are explicitly dependent — if basic availability fails, the metadata and content suites do not run, which stops a single outage from producing hundreds of misleading failures. Element targeting is restricted to stable test identifiers rather than styling selectors, with the deliberate exception of metadata, so a design change does not masquerade as a migration defect. Blanket retries are set to zero, with retries permitted only for specific network status codes, because a suite that retries everything is a suite that hides intermittent real breakage. And failures are emitted as structured records rather than as prose, so the migration team gets a list they can work through rather than a report they have to read.
What was built
Three test projects with explicit dependencies — availability and static assets first, then search metadata including titles, descriptions, canonical links and image alt text scoped to the main content region, then content and interface checks with legacy URL mapping validated against a source-of-truth file, including component-level diagnostics through the platform's own interface and the search backend.
On the table at the end
- Three-stage automated suite with declared dependencies
- Source-of-truth file for expected content and URL mapping
- Structured failure report emitted per run
- Targeting and retry policy written into the suite
What it changed
Replaced 'the site looks fine' with evidence: availability, search-critical metadata and content compared against a declared source of truth, with every failure written out as structured data rather than as a screenshot in a chat thread.
How it ran
- 01
Declare the source of truth
Expected content and legacy URL mapping written into a file, so tests compare against intent rather than against the new site.
- 02
Stage the suites by dependency
Availability first; metadata and content only run if the basics pass, so one outage does not generate hundreds of false failures.
- 03
Protect search visibility explicitly
Titles, descriptions, canonical links and image alt text checked as their own suite, scoped to the main content region.
- 04
Target stably
Test identifiers rather than styling selectors, so a redesign is never mistaken for a migration defect.
- 05
Refuse to retry the truth away
No blanket retries; retries only for specific network conditions, and every failure emitted as a structured record.
Other work
All case studies →- Capital markets
Giving a bilingual site's content back to its editors
Every string on a bilingual market operator's site lived in code, so a comma was a developer ticket. I moved the copy into a headless CMS without letting the market data follow it.
- Health tech
Taking a live product off another vendor in two weeks
A care-coordination platform changed hands mid-flight. Two weeks to take the credentials, audit what we had inherited, fix what was broken and stand up an environment we controlled.
- E-commerce
Reading the money path first
A small commerce platform was days from taking real payments. I reviewed the trust boundaries before the features and found an order that could mark itself paid.
Something similar on your plate?
Thirty minutes, no deck. I will tell you whether it is worth doing at all.