Why your website rewrite will fail — and what we do instead
The rewrite always starts well. A fresh repository, a modern framework, a design system instead of eleven years of accumulated CSS. Three months later the launch date has moved twice, the parity list has grown instead of shrinking, and somebody found an integration nobody documented — because the old site had to keep earning while the new one was being built, and nobody planned for both.
Rewrites fail for three boring reasons. None of them are about code quality.
1. The bugs are load-bearing
Every long-lived site runs on quiet dependencies: a tracking parameter a partner still validates, a URL structure three campaigns point at, a rounding quirk finance has learned to expect. A rewrite discovers these one customer report at a time, because the parity list was written from the codebase instead of from production traffic. The fix is unglamorous — build the parity list from server logs and analytics, not from the source tree.
2. The URLs are the product
Indexed URLs are equity built over years, and a rewrite spends them in a weekend. The redirect map is the single most valuable artefact of the migration, and it has to exist before the first template is ported. After launch it is a week of 404s in your search console and a quarter of recovery. Keep slugs where you can; where you cannot, map every old path to its closest new intent and verify the map with automated requests, not by spot-checking ten links.
3. Big-bang launch has no undo
Flipping all traffic at once means you cannot compare old and new, you cannot roll back a single broken template, and every regression arrives as one incident instead of a diff. The site is the one system where you can keep both versions live and route between them — so do that.
The migration we run instead
The old site keeps running. New pages ship into the same domain, template by template, highest-traffic first. Redirects land with each template. Analytics compare old and new per template while the rest of the site is untouched. When a template holds up for two weeks it replaces the old one and the old route redirects. When one does not, you fix one template instead of relaunching a website.
- Inventory URLs and traffic first — the redirect map starts from logs, not memory.
- Sign off the parity list with whoever owns the exceptions.
- Migrate by template, highest-traffic pages first.
- Ship redirects with each template, verified by request, not by eye.
- Keep a perf budget as the acceptance criterion — if the new page is slower than the old one, it is not done.
- Delete the old code only when the numbers hold for a full comparison window.
When the rewrite really is the answer
Sometimes the old system cannot be incrementally improved: the framework is end-of-life, the app renders everything client-side and cannot be indexed, security debt means the code cannot ship as-is. Those are real rewrites — and even then the migration above still applies. The decision to rewrite and the decision to launch big-bang are separate decisions, and only the first one is ever defensible.
