Refactor and Re-architect
Changing the application's structure — the most expensive migration strategy, justified only where the structure itself is the constraint.
Definition
Refactoring changes internal structure without changing behaviour. Re-architecting changes the structure at a system level — decomposing a monolith, replacing a data model, moving to an event-driven design.
When it is justified
Only when the structure itself is the binding constraint:
- Change cost is high and rising, evidenced by lead time in that area.
- A component's resource profile is fundamentally incompatible with the rest.
- A regulatory or residency requirement cannot be satisfied by the current structure.
- The technology is at end of life with no upgrade path.
"It is old" and "it is not how we would build it now" are not justifications. Working, supported, low-change systems should be left alone.
Incremental, never big-bang
Rewrites of long-lived systems fail at a well-documented rate, for structural reasons rather than incompetence:
- The requirements exist only in the code's behaviour, including behaviour nobody intended and some customer now depends on.
- The business does not stop changing, so the new system chases a moving target while the old must still be maintained.
- No value lands until the end, so the project is cancellable for its entire duration and receives no corrective feedback.
The incremental alternative — strangler fig — inverts all three: value lands progressively, each slice is validated in production, and the work can be paused in a stable state.
The sequence that works
- Insert a routing facade, everything still pointing at the existing system. A no-op release that proves the routing, observability and rollback.
- Extract one capability, chosen for learnability rather than importance.
- Run both and compare for read paths — serve the old result, log the differences. This is the only reliable way to discover undocumented behaviour, and it will find dozens of cases.
- Move the data with the capability, or accept the old system as system of record with a defined synchronisation.
- Repeat, and decommission as you go.
The characteristic failure
The migration that never finishes. The last 20% — rare capabilities, batch jobs, reports, partner integrations — is the hardest. Funding runs out and the organisation permanently operates two systems, which is strictly worse than either alone.
Guard against it: budget decommissioning as explicit work, and track "capabilities remaining on legacy" as the primary metric rather than capabilities delivered on the new system.
Interview question
"When would you re-architect rather than replatform, and how would you sequence it?"