Architecture guide

How do you migrate out of a monolith incrementally?

The rewrite that runs alongside the existing system almost never lands. The old system cannot be frozen because the business still needs changes, so the new one is permanently chasing a target that moves at the same speed it does, and the cutover keeps slipping until someone cancels it. Incremental extraction is slower on paper and it is the only version that reliably finishes, partly because it is allowed to stop early.

Why does the parallel rewrite fail?

Because the monolith keeps changing while the replacement is built. Every feature shipped to the old system is a feature the new one must also implement before cutover, so the finish line moves at roughly the speed of the team building towards it. Feature freezes are proposed to solve this and are almost never granted, because the business did not commission a rewrite in order to stop competing.

The second reason is that a big cutover concentrates all the risk into one night. Everything that was wrong about the new system is discovered simultaneously, under time pressure, with a rollback that is complicated by data written during the attempt.

Incremental extraction inverts both properties. The old system keeps receiving changes, each extraction is small enough to reverse, and value arrives during the migration rather than at the end of it. That last point is what keeps a multi-year programme funded.

How does the strangler pattern work in practice?

You put something in front of the monolith that can route requests, then move one capability at a time behind it. New code goes into new services, the router sends the relevant traffic there, and the monolith shrinks over time without ever being switched off in one step.

The router is usually an existing component: an ingress controller, an API gateway, or a reverse proxy already terminating traffic. What matters is that routing decisions can be made per path or per header without a code change in the monolith, so extraction and rollback are configuration operations rather than releases.

The precondition people miss is that the seam has to be somewhere requests actually arrive. If a capability is only reachable through internal function calls deep inside the monolith, there is nothing at the edge to route, and the first piece of work is introducing an internal interface at that point rather than extracting anything. That intermediate step is worth doing anyway, because it makes the eventual extraction a change of transport rather than a redesign.

Which patterns should you use for each move?

Four, chosen by how tangled the code is and how much the data is shared. Most migrations use several in different places, and using the wrong one is what turns a two-week extraction into a quarter.

PatternWhat it doesUse whenRisk
Strangler facadeRoute selected requests to a new service at the edgeThe capability has its own entry pointsNone if routing is reversible by configuration
Branch by abstractionIntroduce an interface, add a second implementation, switchThe capability is reachable only from insideThe abstraction outlives its purpose and sticks
New feature outsideBuild the next capability as a service from the startSomething genuinely new is being commissionedThe new service still needs the monolith's data
Replicate then cut overCopy data to the new owner, read there, then write thereThe data is shared by many parts of the monolithDivergence between copies during the overlap

Which service should you extract first?

Something with few inbound dependencies, clearly owned data, and a specific reason to be separate. The first extraction is a rehearsal for the platform work, the deployment pipeline, the tracing and the on-call arrangements, so its value is mostly in what it teaches. Choosing the most business-critical component for that rehearsal is how migrations acquire a reputation for causing outages.

Resist the opposite temptation as well. A trivial component with no reason to be separate teaches you the pipeline and then sits there as a service that adds a network hop for nothing. The best first candidates usually have an honest justification already: a workload with a different scaling profile, a component a second team wants to own, or something needing a runtime the monolith cannot host.

A frequently better answer is not to extract anything first. Build the next new capability outside the monolith instead. It has no legacy data to untangle, it exercises the entire platform end to end, and if the approach turns out to be wrong you have learnt it on something small rather than on a component the business depends on.

How do you move the data?

In stages, with reads moving before writes. Stand up the new service's database and replicate the relevant data into it continuously, usually with change data capture from the monolith. Point the new service's reads at its own copy while the monolith remains the writer, and compare results for a while: run the same query against both and log the differences. That comparison period is where you find the assumptions nobody documented.

Then move the writes, once, with the monolith reading from the new service afterwards rather than from its own tables. The intermediate state where both systems write to their own copies should be avoided if at all possible, because reconciling two writers is genuinely difficult and the bugs it produces are data corruption rather than errors.

Where dual writing cannot be avoided, make one side authoritative and treat the other as a projection to be rebuilt rather than repaired. Anything else requires conflict resolution rules, and writing those correctly is harder than the extraction that motivated them.

How do you know when to stop?

When the remaining monolith is no longer causing the problem you set out to solve. A migration does not have to finish, and the end state of a well-run one is frequently a smaller monolith surrounded by a handful of services that had specific reasons to exist. That is a legitimate architecture, not an abandoned project, and it costs far less to operate than a fully decomposed estate.

The signal to stop is that extractions stop having a named benefit. As long as each move is justified by an autonomy, scaling or runtime need, keep going. When the next candidate is being extracted because it is the next one on the diagram, the migration has become an end in itself and the remaining budget is better spent on the product.

A useful check at any point: list the extractions completed so far and, for each, the specific improvement it delivered. If several have no answer, the criteria being used are not working, and continuing will produce more of the same.

Common questions

What is the strangler pattern?
An incremental migration approach where a router in front of an existing system sends selected requests to new services, one capability at a time, so the old system shrinks without ever being switched off in a single step. The routing usually lives in an ingress controller, gateway or reverse proxy, and extraction becomes a configuration change that can be reversed rather than a release that cannot.
Why do big-bang rewrites of monoliths fail?
Because the old system keeps changing while the replacement is built, so the finish line moves at roughly the speed of the team approaching it, and feature freezes are rarely granted. A single cutover also concentrates every undiscovered problem into one night, with a rollback complicated by data written during the attempt. Incremental extraction delivers value throughout, which is also what keeps it funded.
Which part of a monolith should you extract first?
Something with few inbound dependencies, clearly owned data, and a real reason to be separate, such as a different scaling profile or a second team wanting ownership. The first extraction mainly teaches you the pipeline, tracing and on-call arrangements, so the most business-critical component is the wrong rehearsal. Often the better move is building the next new capability outside the monolith instead.
How do you split a database during a migration?
Move reads before writes. Replicate the relevant data into the new service's database continuously, point the new service's reads at its own copy while the monolith still writes, and compare the two for a period to surface undocumented assumptions. Then move the writes once, with the monolith reading from the new service afterwards. Avoid a state where both systems write their own copies.
Do you have to fully decompose a monolith?
No. A smaller monolith surrounded by a handful of services that each had a specific reason to exist is a legitimate end state and costs less to operate than a fully decomposed estate. Stop when extractions no longer have a named benefit. If the next candidate is being extracted because it is next on the diagram, the migration has become an end in itself.

More on Microservices architecture

Let’s create something out of this world together.

Have a project in mind? Contact us for expert design and development solutions. Let’s discuss how we can help grow your business.

Azaadi Offer

Claim a free security assessment

Until 31 August we're covering the cost of a full vulnerability assessment and penetration test. Mention it in your message and we'll scope it with you.

  • Web application testing, authenticated and unauthenticated
  • Mobile application testing across iOS and Android
  • External network and infrastructure assessment
  • Manual exploitation by engineers, not scanner output

Testing and the report are free. Fixing what we find is quoted separately, with no obligation to accept.

Read the full offer

Tell us what you are trying to build and we will tell you plainly whether we are the right people for it. Book a call with an expert to work through the detail, or ask for a fixed quote if the scope is already clear. No obligation either way.

Four fields is all we need to get started.

Fastnexa Logo

© 2026 fastnexa. All rights reserved.