---
title: "Modernizing a legacy application: where to start"
description: "Where to start modernizing a legacy application: assess it, stabilize production, build a test safety net, then replace it piece by piece instead of rewriting."
canonical: https://sdk.enterprises/en/insights/modernising-a-legacy-application-where-to-start
language: en
---

# Modernizing a legacy application: where to start

Updated: 2026-09-26

> Start modernizing a legacy application by writing down why it has to change, then assess the code and production together. Stabilize the system and put tests around the behavior the business depends on before changing its structure. With that safety net in place, replace the system piece by piece, move data deliberately, and keep a full rewrite for the rare case where little is worth keeping.

## Name the business reason before you touch the code

Modernization is expensive, so start with the reason. Common ones are a runtime or framework past end of life, changes that take weeks because every release breaks something, a system that only one person understands, or a platform that cannot support what the business needs next. Each reason points to a different first step.

Write the reason down with a measure you can check later, such as how often you release, how many incidents you have, or how long a typical change takes to reach users. Without it, modernization becomes an open-ended engineering project that is hard to defend at the next budget review.

## Assess the code and production before deciding anything

An assessment tells you what you actually have. Keep it short and make it end with a written report and a recommended first step. Read the code, but also read production: logs, incidents, slow queries and the way releases are done. The worst problems often sit around the code rather than in it.

- Runtime, framework and library versions, and which of them no longer receive security fixes
- Which parts change most often and which break most often, from version history and the incident log
- Test coverage on the paths the business depends on
- How the application is built, configured and deployed, and who is able to do it
- The data model, its size, and which other systems read or write the same database
- The people who know the system, and what only they know

## Stabilize production first, so the work has a steady base

If the system fails every week, modernization will be interrupted every week. Fix what causes incidents first: add monitoring and alerts on critical paths, automate the build and deployment so releases are repeatable, and move secrets and configuration out of the code.

These steps pay off immediately and make every later step safer. They also show early whether the team can change the system without breaking it, which is worth knowing before you commit to a larger plan.

## Build a test safety net around the behavior you rely on

Legacy code usually has few tests, and its documented behavior rarely matches its real behavior. Before changing the structure, write characterization tests: tests that record what the system does today, including its odd edge cases, so that any change in behavior shows up as a failing test.

Start at the edges, with tests that call the application through its API or user interface and check the results, because they survive internal changes. For calculations and reports, replay real inputs through the old and new code and compare the outputs. Add finer-grained tests to each part as you refactor it. Our article on upgrading a critical Java 8 application shows the same safety net applied to a runtime upgrade.

## Replace the system piece by piece instead of rewriting it

A full rewrite looks clean on paper, but the old system keeps running and changing while the new one catches up, and every undocumented behavior has to be rediscovered along the way. That is why rewrites so often take longer than planned while the business waits.

The usual alternative is the strangler fig pattern. Put a routing layer, such as a reverse proxy or an API gateway, in front of the legacy application. Build one capability at a time in the new code, and route traffic for that capability to it once it is proven. The old system shrinks until it can be switched off, and the business gets value at every step.

A rewrite can still be the right call: when the codebase is small and its behavior well understood, or when the platform it runs on cannot be kept alive long enough for gradual replacement. Decide with written criteria, not frustration.

## Treat the data as a migration of its own

Code can be replaced in slices; data is harder to split. While the legacy and new code share one database, every schema change has to be coordinated. Decide early which system is the source of truth for each kind of data, and avoid two systems writing the same record without a rule for which write wins.

When a capability moves, move or synchronize its data deliberately: migration scripts tested against a copy of production, or continuous synchronization while both systems run. Plan how you will reconcile the two, for example with daily counts and checksums, and keep the ability to switch back until the numbers match.

## Sequence the work by risk and value, and show progress early

Order the work so that each step either reduces risk or delivers something the business can see. A common sequence is to stabilize and automate, add tests, upgrade the runtime, then extract the capabilities that change most often. Parts that are stable and rarely touched can wait, sometimes indefinitely.

Keep the plan short and review it after each step, because what you learn will change the order. Our engineers have worked this way on critical systems. Through Sopra Steria, they led a Java 8 to 16 migration of a critical gas day-trading application, and as part of the Crédit Agricole cloud program team we assessed each application we migrated to decide whether to upgrade or rebuild it. If you want an assessment of your own system, or a team to carry out the plan, SDK Enterprises does both under one contract.

## Key takeaways

- Write down the business reason for modernizing, with a measure you can check later.
- Assess code and production together before choosing between upgrade, gradual replacement and rewrite.
- Stabilize production and put characterization tests around critical behavior before changing the structure.
- Replace the system piece by piece behind a routing layer unless a rewrite is clearly smaller and safer.
- Plan data ownership, synchronization and reconciliation as a migration of its own.

## FAQ

### Should we rewrite our legacy application from scratch?

Usually not. A rewrite competes with a system that keeps changing and has to rediscover behavior nobody documented. Replace it gradually unless the codebase is small and well understood, or tied to a platform that cannot be kept running.

### How long does it take to modernize a legacy application?

It depends on the size of the system, its test coverage, how tangled its data is and how much has to change. A short assessment gives you a realistic plan and a first step small enough to finish and measure, rather than one date for the whole effort.

### Can we keep shipping features while we modernize?

Yes, and you should. Gradual replacement lets the team deliver features in the new code while the legacy system keeps running. Agree how much of the team's time goes to modernization, so feature work does not quietly absorb it.

## Start from your need

- [Fractional CTO](https://sdk.enterprises/en/fractional-cto)

## Related services

- [Custom software](https://sdk.enterprises/en/services/product-engineering)
- [Technical audit and consulting](https://sdk.enterprises/en/services/consulting)

## Further reading

- [How to upgrade a critical Java 8 application to modern Java](https://sdk.enterprises/en/insights/upgrading-legacy-java)
- [Migrating hundreds of legacy apps to AWS without stalling](https://sdk.enterprises/en/insights/migrating-hundreds-of-apps-to-aws)
