Every legacy system reaches a point where someone proposes replacing it. The argument is always persuasive: the code is unmaintainable, nobody understands it, each change takes weeks, and a clean rebuild on modern foundations would take eighteen months. The trouble is that the eighteen months is measured against a specification nobody has written, for a system whose behaviour nobody fully knows, while the original keeps changing underneath. Full rewrites are the most commonly attempted and most commonly abandoned modernisation strategy there is.
The reason they fail is not incompetence. It is that a legacy system's real specification is its behaviour, including a decade of undocumented exceptions - the customer type that is billed differently, the report finance depends on that nobody mentioned, the workaround from 2019 that three departments now rely on. A rewrite must reproduce all of it before it can replace anything, and it discovers each piece late, usually from an angry user during a cutover weekend.
The alternative is to strangle the old system rather than replace it. You put a routing layer in front, move one capability at a time to new code behind it, and send traffic for that capability to the new implementation while everything else continues untouched. The old system shrinks gradually. At every point you have something in production, and at every point you can go back by changing a route.
Choosing the first capability matters more than anything technical. It should be something with a clean boundary, real business value, and consequences you could survive - not the billing engine, and not something so peripheral that nobody notices it worked. The first slice is really about proving the pattern and building the routing, testing and deployment machinery that every subsequent slice will reuse. Expect it to take disproportionately long and do not read that as a bad sign.
Two things make or break the middle phase. The first is data: for a period, both systems are live, and you must decide for each entity which system owns the truth and how the other learns about changes. Duplicated writable state is where these programmes actually die. The second is discipline about the old system - a freeze on new features in the legacy codebase, so you are not modernising a moving target. Without that, teams find themselves reimplementing capabilities that were added after the migration of that area began.
The honest trade-off is that this approach is slower in total elapsed time than a rewrite that goes perfectly, and considerably faster than the far more common rewrite that stalls. It also delivers value continuously rather than at the end, which matters more than it sounds: programmes that show results every quarter survive leadership changes and budget cycles, and programmes that require two years of faith before anything ships usually do not get two years.
There is one case where a full rewrite is right: when the system is small enough that a couple of engineers can hold all of it in their heads, or when the underlying platform is genuinely dead - unsupported runtime, no available skills, a vendor that has left the market. If you are considering a rewrite for any other reason, the strangler route will almost certainly get you there with less risk.