Direct answer
A full rewrite wins when the legacy system's structure fights every incremental change so hard that the accumulated cost of working around it, in time, in bugs, in the parts of the team's attention it consumes, exceeds a realistic (padded) estimate for building it again from what you now know. What has to go right: the team genuinely understands the system's current behavior well enough to not silently drop requirements, the business can tolerate a real delivery gap, and there's a credible plan for the parts of the estimate that are hardest to predict, data migration and the long tail of edge cases nobody remembers exist until they break in production.
Structured elaboration
The risks a rewrite introduces that incremental work avoids:
- The estimate is a guess dressed as a plan. You cannot fully know what a legacy system does until you've read every path through it, and if you could do that cheaply, you probably wouldn't need a rewrite. Rewrites reliably underestimate the "long tail," the 20% of behavior that's undocumented, weird, and only matters for edge cases, because that's exactly the part that's hardest to discover in advance.
- All-or-nothing delivery. An incremental effort can stop, ship partial value, and reassess. A rewrite typically can't ship real value until most of it is done, which means the business is exposed to the full cost of the effort before seeing any of the benefit, and a rewrite that stalls at 80% delivers zero value for the investment made.
- Data migration risk concentrates at the end. Incremental approaches migrate data piece by piece, catching problems early on a small blast radius. A rewrite often defers data migration to a single cutover at the very end, which is exactly when the team has the least remaining slack to absorb a surprise.
The risks incremental work introduces that a rewrite avoids:
- Running two systems for longer than planned, with the ongoing cost and the risk of the migration simply never finishing.
- The seam itself becoming a source of bugs, translation errors at the boundary between old and new that a from-scratch rewrite wouldn't have to deal with.
- Slower overall delivery of the target end state, since incremental work is deliberately paced to be safe rather than fast.
Concrete mitigations for the rewrite risks: build characterization tests against the legacy system's actual behavior before writing a line of the replacement, so the estimate is grounded in observed behavior rather than assumed behavior; plan the data migration and cutover as a first-class, staged piece of the project rather than a final step; and set an internal checkpoint (not a public commitment) partway through where the team honestly reassesses whether the estimate is holding, with permission to fall back to a hybrid approach if it isn't.
Worked example
A retrospective example: a team decided a legacy inventory system's coupling to a proprietary rules engine made incremental extraction impractical, so they chose a rewrite. What made it work: they spent the first month purely on characterization testing against the legacy system, capturing behavior for every product category and edge case they could enumerate, before writing any new code. That testing surfaced a rounding rule for one product category that looked like a bug but turned out to be a deliberate accommodation for a regulatory requirement in one region, exactly the kind of hidden logic a rewrite risks silently dropping. Because they'd captured it in a test before starting, the new system preserved it correctly, and the team could point to a passing test suite, not just confidence, when they cut over.
An architectural decision that limited scale, brought up in the same retrospective: the original system had used a single shared table for all regions' inventory data, which made the regulatory rounding rule and a dozen similar region-specific rules invisible in the schema and discoverable only by reading application code path by path. The rewrite's replacement schema made region-specific rules an explicit, first-class concept, directly because the team had been burned by how hard the old shape made those rules to find.
Trade-offs and pitfalls
The single biggest risk-reducer for a rewrite is treating "we understand the current behavior" as a deliverable to prove, via characterization tests against real behavior, rather than an assumption to proceed on. Teams that skip this step and start writing new code based on what they believe the system does, rather than what it's actually observed to do, are the ones whose rewrites silently change behavior and discover it in production months later.