Long-lived embedded software is rarely old for just one reason. It may be expensive to replace, closely coupled to hardware, difficult to test or simply dependable enough that nobody wanted to disturb it. Modernisation begins by separating genuine liabilities from the knowledge that still protects the operation.
1. What behaviour is genuinely business-critical?
Begin with observable outcomes, not modules. Which timings, interfaces, safety properties, data records and operator workflows must remain unchanged? A requirement that sounds obsolete may encode a constraint imposed by equipment or field operation.
Create a short list of invariants: the things a replacement must preserve. This becomes the basis for regression tests and migration acceptance.
2. Where is the operational knowledge stored?
Some knowledge will be in requirements and code comments. Much of it may exist only in tests, support scripts, configuration files and the habits of experienced operators. Interview the people who recover the system when it fails. Their shortcuts often reveal undocumented failure modes.
3. Can the current behaviour be measured?
Rewriting without a behavioural baseline turns acceptance into opinion. Capture timings, protocol exchanges, output data, resource use and known edge cases before changing the implementation.
- Record representative device traffic.
- Identify outputs that can be compared automatically.
- Collect failure and recovery scenarios, not only successful operation.
- Preserve representative production data with appropriate controls.
4. Which boundaries are stable enough to preserve?
A full rewrite is often unnecessary. Hardware interfaces, message contracts or data formats can form boundaries around incremental change. A compatibility layer may not be architecturally fashionable, but it can create a controlled route away from a risky component.
5. What is forcing the change now?
The modernisation plan should respond to a concrete pressure: unavailable hardware, unsupported tools, security exposure, recruitment difficulty, poor testability or a required feature. Different pressures justify different interventions. Replacing everything because the language is old is rarely a sufficient business case.
6. How will old and new coexist?
For an operational system, migration is part of the architecture. Decide how versions will be deployed, how data will move, how interfaces remain compatible and how the team will recover if the new component fails. If rollback is impossible, the verification burden rises substantially.
7. Who will operate the result?
A technically successful replacement can still create a support problem. Plan diagnostics, documentation, deployment and knowledge transfer alongside implementation. The goal is not a new dependency on the modernisation team; it is a system the owning organisation can understand and evolve.
A useful first deliverable
Before committing to a rewrite, produce a concise system map, risk register, behavioural baseline and staged migration proposal. That work is valuable even if the decision is to retain most of the existing system. It turns “the code is old” into a set of engineering decisions that can be evaluated.