The simple version

The engineers who built a system are too close to it to estimate rebuilding it accurately. Their knowledge becomes a liability, not an asset.

The scenario that plays out everywhere

A VP of Engineering calls a meeting. The old system is a mess. Customers are complaining about reliability, the codebase is five years of scar tissue, and every new feature takes three times longer than it should. She asks the team: how long to rewrite this properly?

The lead engineer, who has lived in this codebase since the beginning, says six months. Maybe eight. The team nods.

Two years later, they’re not done.

This is not a story about incompetent engineers. The team was skilled. The estimate was sincere. The problem is structural, and it happens so reliably that you can almost set your watch to it.

Why deep knowledge works against you here

When you’ve spent years in a system, you stop seeing a large part of it. Not because you’re careless, but because expertise works by compressing information. You no longer consciously register the seventeen edge cases in the payment flow because you internalized them long ago. They’re not on your mental checklist anymore. They’re just how things work.

When you sit down to estimate a rewrite, you’re essentially doing an inventory of the system in your head. But your mental inventory is missing all the things you’ve stopped thinking about. The estimate you produce reflects the system you consciously think about, not the system as it actually exists.

There’s a related problem: the original builders remember why they made the decisions they made. They know that the weird date-handling logic exists because of a specific customer in a specific timezone with a specific contract requirement. When they estimate the rewrite, they mentally replay building the system under ideal conditions, with all that context loaded. They forget that they’ll spend weeks rediscovering the reasons for each strange decision.

Two diagrams comparing a developer's mental model of a codebase to its actual structure, showing the gap between perception and reality
The mental inventory and the actual inventory are never the same size.

The second trap: optimism about what you’ll do differently

Rewrite proposals almost always come with a companion promise: this time we’ll do it right. We’ll use the new framework. We’ll separate concerns properly. We’ll write tests first. And those intentions are genuine.

But every one of those improvements is additional scope. The estimate usually covers “rebuild what we have.” It rarely accounts for the ambition that gets layered on top once the project starts. Scope creep isn’t just about external stakeholders adding features. Engineers add scope to themselves, because a rewrite feels like permission to fix everything that has bothered them for years.

This is why rewrites that start as “like the old thing but cleaner” tend to end as “a substantially new product that we’re still trying to get to feature parity with the original.” Netscape’s attempt to rewrite their browser from scratch, which Joel Spolsky wrote about in 2000, burned years and cost them the market. The engineers knew the old code well. That didn’t help them.

The things you only discover by running

Production systems accumulate behavior that nobody designed. Bugs that customers worked around and now depend on. Load patterns that only appear at 11pm on Fridays. Integrations with third-party APIs that behave differently than their documentation says. A weird but functional caching behavior that accidentally prevents a race condition.

None of this is in any spec. It exists in the gap between what the system was supposed to do and what it actually does. When you estimate a rewrite, you’re pricing the spec. When you build the rewrite, you discover the gap, and closing it is often more work than the original estimate for the whole project.

The engineers who built the old system have a slightly better chance of noticing these things mid-rewrite, but they still have to rediscover them, often through painful production incidents. The irony is that their familiarity with the old system can slow this process down, because they assume the new system will behave the way the old one did, until it doesn’t.

This connects to a point worth understanding about production complexity generally: why fixing a production bug is harder than writing the code in the first place. Rewrites surface this problem at massive scale.

So who should estimate it, and what should they do?

The engineers who built the system should absolutely be involved in the rewrite, and their knowledge is genuinely valuable for execution. But the estimate should be stress-tested by people with distance.

A few things that actually help:

Get someone who wasn’t there to read the codebase and enumerate what exists. Not what the system does conceptually, but what code actually exists. Modules, integrations, data transformations, error handling paths. The gap between this list and what the original team came up with is usually instructive.

Treat the original estimate as a floor, not a forecast. If the engineers say six months, experienced project managers who have run rewrites know to at least double it. Not because engineers are bad at math, but because the structural problems above are consistent and predictable.

Ask specifically about integrations and edge cases, not just features. The feature list is the easy part. Make the team enumerate every external system the codebase touches, every data migration that needs to happen, every customer-specific behavior that’s been quietly maintained for years. The estimate tends to grow substantially during this conversation.

Consider whether you need a rewrite at all. Many rewrite proposals are solving an organizational or process problem, not a technical one. Adding engineers to a late project makes it later, and starting a rewrite to escape the debt of an old one sometimes just relocates the problem with extra steps.

The original builders of a system are your best source of truth about why the system is the way it is. They are a poor source of truth about what it costs to replace it. Keeping those two things separate is one of the more expensive lessons in engineering management, and most organizations learn it by paying for it.