Cloud & Platform Engineering
Legacy Application Modernization: Rehost, Refactor or Rebuild?

Quick answer
Key takeaway
A decision framework for modernizing a legacy application: when to lift and shift, when to refactor, when to rebuild, and how the strangler approach keeps the business running while you do it.
Start with the reason, not the technology
Teams modernize for different reasons, and the reason decides the approach. Some are escaping a data centre contract or end-of-life hardware. Some cannot ship features because every change risks breaking something unrelated. Some face security or compliance findings the old stack cannot satisfy, and some cannot hire anyone who knows the language the system is written in.
Write the reason down with a measurable target, such as deploys per month, recovery time after an incident, or infrastructure cost per transaction. Without that target a modernization drifts into a rewrite that never finishes, because nobody can say what 'done' means.
The three honest options
Rehost, often called lift and shift, moves the application to cloud infrastructure with minimal change. It is the fastest route and the right one when the goal is leaving a data centre by a deadline. It delivers little else: the architecture, the deploy pain and most of the cost structure come along unchanged.
Refactor keeps the system but changes its structure: extracting a module into a service, moving state out of the web tier, replacing a hand-rolled job runner with a managed queue, introducing automated tests around the riskiest paths. It suits systems whose core logic is sound but whose delivery is slow. Rebuild replaces the system and is justified only when the existing code cannot be made safe to change, or the business process it encodes has itself changed.
Why big-bang rewrites fail, and the strangler alternative
A full rewrite has to match years of accumulated behaviour, including behaviour nobody remembers deciding on, before it delivers any value. Meanwhile the old system keeps changing, so the target moves. The risk is concentrated at a single cutover date.
The strangler approach avoids this. Put a routing layer, an API gateway or reverse proxy, in front of the legacy system. Then peel off one capability at a time: build it as a new service, route a small share of traffic to it, compare results with the legacy path, and widen the share when they agree. Each slice ships independently, can be rolled back by flipping a route, and the legacy system shrinks until it can be switched off.
Data is the hard part
Code can be rewritten slice by slice; a shared database cannot be split so easily. Plan the data migration as its own track. Common patterns include having the new service own its tables and expose them back to the legacy system through an API, syncing data between old and new stores with change data capture during the transition, and running both paths in parallel while a reconciliation job proves they agree.
Resist the temptation to let new services read the legacy database directly. It feels quick, and it quietly rebuilds the coupling you are trying to remove.
Build the safety net first
Before touching the code, make changes cheap to verify. Add characterization tests that record what the system currently does for important inputs, set up a CI pipeline that builds and tests on every change, and put observability in place: structured logs, metrics for the key business flows, and tracing across the old and new paths. Modernization without this is guesswork, and with it each step is a small, reversible bet.
A realistic sequence
A sequence that works for many teams: assess and map dependencies, stabilize with tests and CI, containerize and move to managed infrastructure, then extract the highest-value or highest-pain capability first. Pick something with clear boundaries, such as notifications, reporting or authentication, so the first slice proves the pattern without risking the core transaction flow.
Review after each slice against the target you wrote down at the start. If deploy frequency or recovery time is not improving, change the plan before the next slice, not after the last one.
FAQ