Replacing a legacy system: step by step, not on one cut-over date
How to replace a grown legacy system module by module: a router in front of it, an order derived from dependencies, and a parallel run with a comparison.
This translation was produced automatically using AI. The German version is the editorially reviewed original.
Take a made-up example: a wholesaler of industrial supplies. Its merchandise management system has grown in-house over many years: master data, customers, articles, orders, warehouse, purchasing, invoices, quotes, dunning and shipping, ten business modules in one application. Now a customer portal is supposed to hand over orders directly, and the legacy system has no interface for that which anyone still wants to touch.
The obvious plan is a rebuild and a switch-over on a fixed date. The other plan moves the modules one at a time, lets old and new run side by side for a while and only switches the legacy system off once nothing uses it any more. Which plan holds depends less on the technology than on the dependencies between the modules, and those can be written down and worked through in advance.
01. Why a cut-over date puts so much on one day
With a switch-over on a cut-over date, everything happens at once: the data is transferred, every interface points to the new system, every user works in new screens from Monday. Each of these steps can succeed on its own and still fail in combination, and the fault only shows once the first real order runs through.
A cut-over date is like moving a workshop over one weekend. If one machine jams on Monday, the whole hall stands still, because the old layout has already been taken down. On top of that, a switch-over is hard to reverse once the first records exist in the new system: whoever switches back has to bring that data back into the legacy system.
This does not mean a cut-over date is always wrong. It means that the risk of a cut-over date grows with the number of modules that have to work together on that day. A step-by-step replacement keeps exactly that number small.
02. A router in front of the legacy system
Martin Fowler describes the approach under the name Strangler Fig, after a fig that grows up a host tree until it replaces it. New functions are built separately from the legacy system, both run side by side during the transition, and behaviour gradually moves from the old system to the new one. Fowler stresses that breaking the system down into pieces that can be replaced one at a time is the actual core of the approach.
Technically, this needs a place where it can be decided which system handles a request. That can be an interface in front of the system which the portal, warehouse and accounting already talk to, or a database view behind which the tables are moved. This router is transitional architecture: it costs effort although it disappears again at the end, and it is still the reason why each individual move stays small.
If there is no such place, because users and external systems write straight into the legacy database, the replacement starts by building one. This first step brings nothing new for the business, but it shows who actually uses the legacy system.
03. Which module moves first
Not every module can move at any time. Invoices need orders, orders need customers, and dunning needs invoices. A hard dependency of this kind means: a module can only run in the new system once its prerequisite already runs there, or it moves in the same stage as that prerequisite.
This gives a simple rule. Peripheral modules that no other module relies on move first, in the example shipping and quotes. An early move at a place with little traffic shows whether router, data synchronisation and operations work before a module the revenue depends on is due.
Modules that need each other, or whose prerequisite has to wait a long time itself, are harder. They lead to coupled moves, in which two modules change over in the same stage. A coupled stage is a small cut-over date inside the step-by-step replacement, and it deserves the most thorough preparation.
04. Working through the stage plan yourself
The calculator applies these rules. It takes a list of business modules, assigns an adjustable share of hard dependencies and plans stages from them in which at most the set number of modules move. Switch between cut-over date and step by step, and watch in which stage the invoices module changes over and whether that stage is outlined with a dashed line as a risk.
Bars: modules per stage · Line: share of requests in the new system
- Legacy system
- Parallel run
- New system
- Share of requests in the new system
- Modules waiting for their prerequisite (count)
- Cut-over risk: coupled move or everything at once
- Stage 1 Shipping, Quotes Dunning waits for Invoices
- Stage 2 Purchasing, Warehouse Invoices waits for Orders
- Stage 3 Articles, Customers Orders waits for Customers
- Stage 4 Orders, Invoices Invoices coupled to Orders
- Stage 5 Dunning, Master data
- Stages until replacement
- 5
- At most in parallel
- 2 of 10
- Modules in stage 1
- 20 %
- Stages with cut-over risk
- 1
With the example values of the default setting, ten modules, two modules per stage and three hard dependencies, the plan has five stages. Invoices only move in stage 4, coupled to orders, which in turn wait for customers. Calculated as a cut-over date, all ten modules change over in one stage, and all three dependencies become coupled moves. With only one module per stage the risk disappears completely, but the plan grows to ten stages.
The numbers are stages, not weeks. How long a stage takes depends on the module, the data and the parallel run. What the calculator reliably shows is the structure: which modules wait, where couplings arise and which lever resolves them.
05. A parallel run means comparing
While a module moves, old and new run in parallel for one stage. That only adds safety if both results are compared. The router sends the same request to both systems, the legacy system stays authoritative for now, and every difference ends up in a log that someone reads.
Before switching over, it should be written down when the parallel run ends: for example once no unexplained difference has occurred over an agreed period and every known special case has run through at least once. Without such a criterion, the parallel run stays in place out of caution, and the team maintains two systems for longer than planned.
Differences are not always faults in the new system. Often the comparison reveals a rule that was never documented in the legacy system, such as a rounding step or a discount that only applies to one customer group. Findings like these belong in the description of the new module before the old one is switched off.
06. Who owns the data during the replacement
The most delicate question in a step-by-step replacement concerns the data. As long as a module exists in both systems, every data object needs exactly one leading system: customer master data is changed either in the old or in the new system, never in both. The other system receives a copy, and the direction of that copy only changes when the module moves.
In practice, this means creating a mapping table for identifiers early, because the new system assigns its own numbers, and deciding how often and in which direction data is synchronised. Letting both ends write at the same time creates conflicts that are hard to resolve later.
07. When a function is needed earlier than its module can move
In the example, the customer portal is supposed to hand over orders early, but the orders module can only move in stage 4. The stage plan alone does not answer this. An interim solution at the router can accept orders from the portal, check them and write them into the legacy system through the existing path until the new module is ready.
Such an interim solution is deliberately transitional code. It should be built so that it can later be placed in front of the new module or removed, and it belongs in the plan with a date for its review. Otherwise the interim solution turns into another legacy system.
08. When a cut-over date is the better choice after all
A step-by-step replacement costs a router, a parallel run and data synchronisation. These costs are not worth it in every case. A small system with few users and no integrations can often be switched over more cleanly on one well-prepared day.
- The system is small: if all modules can be tested in one day, breaking it down brings little.
- There is no place for a router: an application whose data can only be reached through its own user interface is hard to redirect section by section.
- The data model cannot be split: if almost every table is written by almost every module, every stage becomes a coupled move.
- The parallel run costs more than the risk: if a one-day outage is bearable, the preparation can be leaner.
Even then, part of the method remains useful. The list of modules and their dependencies shows what has to work together on the cut-over date, and therefore what should be tested together beforehand.
09. Where you can start
The first steps follow the same logic as the stage plan, and they can be started in-house. First comes a list of business modules with their users, data flows and hard dependencies, counted rather than estimated. Then every connection to other systems is described like a contract: format, direction, behaviour on failure and responsibility.
With this list, a peripheral module can be chosen as the first candidate, and it shows whether router, comparison and operations hold. Which documents a new module needs before another team runs it is covered in the guide Vom Proof of Concept in den Regelbetrieb (German). What needs to be settled for running an application in-house is described in Eine Anwendung im eigenen Haus betreiben, and how to spot shortcuts in the code that make every further move more expensive in Technische Schulden erkennen.
If a service provider is to accompany the replacement, the guide Prototyp weiterentwickeln lassen helps with the selection. An overview of software development at iiterate is on the page Softwareentwicklung.

