Legacy systems frustrate teams because every change feels expensive. The natural response is to imagine a clean replacement. But the old system is rarely only old code. It contains years of exceptions, operating knowledge, integrations and business promises.
Inspect before prescribing
Start with the code, deployment path, data, integrations and change history. Then connect those findings to the business capabilities the system supports. Technical debt matters because of the constraint it creates, not because the code offends modern taste.
The first modernization deliverable should be a clearer picture of the system—not a target architecture diagram.
Separate pain from risk
Slow delivery, fragile releases, unsupported components and poor observability are different problems. They do not all require the same treatment. Some need stabilisation; some need extraction; some can remain where they are.
Earn the right to replace
A replacement becomes credible when the team can name the capability being moved, preserve its real behaviour, migrate its data and operate old and new safely during the transition. Until then, “rewrite” is an aspiration rather than a plan.