Every long-lived system eventually reaches a point where change is slow and risky. The instinct is to rewrite from scratch. The track record of full rewrites — long timelines, frozen roadmaps, feature parity that never quite arrives — suggests another path.
The strangler pattern
Place a routing layer in front of the legacy system. Build new functionality as separate components behind it, and progressively route traffic from old to new, one capability at a time. The legacy system shrinks until it can be switched off.
Find the right seams
- Capabilities with clear inputs and outputs
- Areas with the highest change frequency
- Components causing the most incidents
- Domains that block new product initiatives
Handle data carefully
Data is usually the hardest part. Use change data capture to keep new services in sync during transition, define a clear system of record for each entity at each stage, and run old and new paths in parallel to verify parity before cutting over.
Invest in safety nets first
Before touching anything, add characterization tests around current behavior, improve observability, and automate deployment. These make every subsequent step cheaper and safer.
Modernization is a sequence of small, reversible moves — not a single leap.
Done this way, modernization delivers value continuously. Each migrated capability is faster to change, easier to scale and ready for new features, including AI.