Skip to main content

Use case

Your software still works. Evolving it is the problem.

The application still does what it was built for. But every change takes longer, needs more care, and depends on fewer and fewer people. The question is not whether it is "old": it is what it costs you to move forward.

You may recognise some of this

All of it rarely applies. Two or three of these points are enough to slow a team down for good.

  • Every change risks breaking something else, and nobody really knows what until it ships.
  • Some technical components no longer receive updates, security fixes included.
  • Part of the code is never touched: people work around it rather than go into it.
  • Releases are manual, slow, and happen outside working hours.
  • Adding a feature that looks simple takes an unreasonable amount of effort.
  • Integrations with other tools have become fragile and get repaired case by case.
  • Knowledge of the system lives in one or two people.

What happens if nothing is done

Nothing collapses overnight. That is exactly what makes this hard to decide on.

The cost of change rises quietly
Each evolution needs a bit more care than the last. The maintenance budget eats into the one for new things, without any decision ever being taken.
Unmaintained dependencies become a security matter
A library that no longer receives fixes does not become a problem gradually: it becomes one the day a vulnerability is published.
The system becomes an argument against the business
Requests get refused because they are technically expensive, not because they are bad. The software ends up deciding what the company can do.
One person leaving becomes an operational risk
When nothing about the system is written down, a resignation or a long absence turns an ordinary change into an investigation.

Rewriting is not always the answer

Four paths are defensible depending on the situation. A full rewrite is the most visible one, and rarely the most sensible.

Rewriting is not always the answerWhen it is the right callWhat it involves
MaintainThe system still meets the need, the changes expected are limited, and the technical risk is under control.Update dependencies, document what matters, and accept that the application is not a project. That is a decision, not inaction.
Modernise progressivelyThe system is still fundamentally right, but parts of it get in the way: coupling, no tests, manual deployment, a dated interface.Isolate the risky areas, expose stable interfaces, replace piece by piece. Old and new run side by side for the whole transition.
RebuildA fundamental constraint genuinely blocks progress: an unsuitable data model, an abandoned platform, an architecture that forbids what the business asks for.A long project, with data migration and a period of dual running. Only worth starting with a framed scope and a staged path.
Replace with an off-the-shelf productThe process it supports is no longer a differentiator, and an existing product covers the need without contortion.Accepting that some practices will bend to the product, and taking data and accumulated business rules seriously.

We do not default to the heaviest path. In several situations, maintaining an application properly for two more years is the best economic decision.

Old and new can run side by side

Progressive modernisation is not stopping one system and starting another. At every stage both run, and the share carried by the original application goes down.

Carried by the existing applicationTaken over by the new components
  1. 01

    Stabilise

    Put tests, automated deployment and monitoring back in place. Nothing changes for users.

  2. 02

    Isolate

    Draw a boundary around the risky areas and cut the cross-dependencies that make every change global.

  3. 03

    Expose

    Put the data and the rules behind a stable interface that both old and new can call.

  4. 04

    Replace

    Rebuild one function at a time, with a controlled and reversible switchover.

  5. 05

    Retire

    Remove the code that is no longer needed. While it is still there, it still has to be maintained.

The last stage is the one most often skipped. An old component left in place "just in case" keeps costing in maintenance and in exposed surface.

How we approach it

Before proposing a path, you have to know what the system actually does — which is almost never what the documentation says.

  1. 01

    Understand what exists

    Reading the code, mapping dependencies, inventorying what is deployed and tested. We also talk to users: some business rules only live in their habits.

  2. 02

    Identify the risky areas

    Where a change propagates, which dependencies are no longer maintained, which parts have neither tests nor documentation, and where knowledge is concentrated.

  3. 03

    Decide what stays

    Not every part of a system deserves the same effort. Some are stable and well written: they stay. The conversation is about the rest.

  4. 04

    Secure the interfaces and the data

    Before replacing anything, the exchange points get stabilised and the real state of the data gets checked: duplicates, fields repurposed for something else, incomplete history.

  5. 05

    Modernise in increments

    One area at a time, released regularly, with a rollback available. The system stays usable for the whole duration.

  6. 06

    Migrate the data

    Migration is prepared early, rehearsed, and verified by consistency checks before the switchover. It is the most underestimated part of this kind of project.

  7. 07

    Retire the debt that is no longer needed

    Removing replaced components, access that no longer serves anything, and forgotten environments. Without this step, modernisation adds a layer instead of removing one.

On an old system, data migration often deserves its own scoping: that is where the surprises are, not in the code.

What if nobody really knows the code any more?

This is a common situation, and it does not block a project. It just changes how you start.

  1. The running system is the reference

    What runs in production is the most reliable specification available. You observe it, trace the calls, and reconstruct the actual behaviour before touching anything.

  2. The data tells you the rules

    A field always filled the same way, a value that should not exist, a table nobody writes to any more: the actual content reveals business rules nobody can state out loud.

  3. Tests come before changes

    On untested code, the first useful delivery is often writing tests that describe the current behaviour — without fixing it — so it can then be changed without guessing.

What this can look like

A few shapes this kind of path takes in practice, depending on the starting point.

  • An automated test and deployment pipeline on an application that used to ship by hand
  • A stable API in front of an old system, so other tools stop reaching into its database
  • A rebuilt interface on the most-used screens, with the rest kept as it is
  • A critical module isolated then rewritten while the rest of the application keeps running
  • A data migration with consistency checks and rehearsals before the switchover
  • A retirement plan for replaced components, with their access and environments

These describe possible shapes of a solution, not delivered projects presented as references.

Frequently asked questions

Do we have to rewrite an old application?

No, and it is rarely the best choice. A full rewrite loses years of accumulated business rules, costs a lot, and produces nothing usable for a long time. In most cases it is better to isolate the part that genuinely causes problems and replace that, while the rest keeps running.

Can we modernise without stopping the system?

Yes — that is the whole principle of progressive modernisation: at every stage, old and new run in parallel. Switchovers happen function by function, with a rollback available. It demands more discipline than a one-shot replacement, but it avoids stopping the business.

How do you take over software with incomplete documentation?

By starting from what runs rather than what is written. Reading the code, observing the system in production, analysing the real data and talking to users reconstructs the actual behaviour. The output of that phase becomes the documentation that was missing.

How is the data migration handled?

As a piece of work in its own right, not as a final step. That means analysing the real state of the data early, defining explicit transformation rules, rehearsing the migration as many times as needed, and planning consistency checks after the switchover. This is where most bad surprises happen.

How long does it take?

It depends entirely on the size of the system and the path chosen, and neither is known before scoping. What we can say: progressive modernisation produces usable results continuously, whereas a rebuild delivers nothing until the end.

Let us talk about your application

Tell us what is blocking today. We will tell you frankly which path looks reasonable — including not starting a project right now.