Guides & TutorialsDevelopment

Monolith to Microservices With AI, Without Regressions

A step-by-step strangler fig workflow for decomposing a legacy monolith with AI: where assistants genuinely help (code comprehension, seam finding, test generation) and where architectural judgment and data migrations must stay human.

Toolbit AI - Team
8 min read
Monolith to Microservices With AI, Without Regressions

Can AI turn a monolith into microservices? Not on its own. Use it to read the code, find seams and draft characterization tests, then extract one slice at a time behind a strangler fig facade, and keep service boundaries and data migrations human.

Somewhere in your company there is a service nobody wants to touch. It has run for a decade, it quietly holds the order pipeline hostage, and the one engineer who truly understood its internals left in 2023. Now leadership has decided it must become microservices, and you are the architect who has to deliver that without breaking checkout for a single customer.

This is the part of modernization that vendor demos never show. The hard part is not writing new services. It is that a 400,000-line codebase contains thousands of invisible dependencies, and every extraction is another chance to find one in production on a Friday.

The good news: a proven pattern exists for doing this incrementally, and AI coding assistants have become genuinely useful at the three most expensive steps of AI-assisted legacy code refactoring: understanding the code, finding the seams, and generating tests before you extract anything. The better news: they stay untrustworthy at exactly the two steps that sink projects, deciding boundaries and moving data. That makes the division of labor unusually clean, and this article maps it.

Why the strangler fig still wins

Every serious monolith decomposition starts from the same insight Martin Fowler first described years ago and rewrote in 2024: never replace a system in one cut. A strangler fig germinates in the branches of a host tree, grows around it, and eventually the host dies while the fig keeps its shape. Applied to software: you build the new structure around the old one, move behavior over piece by piece, and decommission a slice of the monolith only when its replacement has proven itself in production.

The mechanics are well documented. Microsoft's Azure Architecture Center guide to the pattern describes the standard setup: a facade or proxy intercepts client requests, initially routing everything to the legacy backend, then progressively rerouting extracted functions to new services. When the old and new sides speak different dialects, you add an anti-corruption layer between them so the new services never inherit the legacy model's quirks.

The reason this pattern dominates is not elegance, it is risk. A cut-over rewrite puts the entire business in play for the duration. A strangler fig puts one small slice in play at a time, and each slice teaches you something about the system you thought you understood. That matters even more with AI in the picture: every AI-generated artifact gets tested against reality in small, reversible steps.

Where AI genuinely earns its keep

Legacy refactoring is mostly reading, and reading is where large language models are strongest. Three jobs in particular have become dramatically cheaper.

Code comprehension at scale. Ask an agentic coding assistant "which tables does OrderService write to, and which other modules call it" and get a defensible answer in minutes instead of a week of spelunking. Coding agents can crawl a whole repository through protocols like MCP, so the answer is grounded in your code, not training data. Reasoning quality matters more than autocomplete speed here; our Cursor vs Windsurf refactoring comparison shows how two agentic editors handle repository-wide changes.

Seam identification. Fowler's article is explicit that legacy systems rarely break apart naturally: there is "considerable work in figuring out how to break it down into manageable pieces" by "identifying seams that we can insert into the system to allow it to be split". That is a mapping exercise, and mapping is what AI does well. Let it enumerate candidate seams: module boundaries, ownership of specific tables, call clusters with few incoming edges. You still make the final call, but the list that took a consultant a month now takes an afternoon.

Test generation before extraction. This is the single highest-value use. The iron rule of safe extraction is characterization tests around the seam before you move a line of code, capturing what the legacy system actually does, bugs and all. AI generates this scaffolding fast: call-path tests, boundary inputs, regression suites for modules nobody has touched in years.

Mechanical transformation. Version and dependency upgrades are the warm-up act before any decomposition, and vendors have shipped real products. Amazon Q Developer Transform upgrades Java 8 and 11 codebases to Java 17 or 21: it builds your project, generates a transformation plan, re-runs your existing unit tests iteratively, and produces a diff you must explicitly accept. The official docs list the constraints: Maven 3.8 or later, and a full build and test cycle within 55 minutes. The agent makes only the minimal changes needed for the target JDK, then a second transformation job handles dependency upgrades. AWS shares a customer report of a 10,000-line Java 8 to 17 upgrade finishing in minutes where manual effort was estimated at over two weeks. Treat that number as vendor-reported, but the mechanics are documented and reproducible.

Where you cannot trust it

Now the uncomfortable half of the map.

Service boundaries are a business decision, not a code decision. Where to cut depends on team structure, domain ownership, and which changes the business wants to ship independently. Fowler ties modernization to Conway's Law for exactly this reason: your architecture will mirror your organization whether you plan for it or not. An AI can propose boundaries that look elegant on a dependency graph yet are operationally wrong because two "loosely coupled" modules are owned by one team that ships them together. No model sees your org chart or your roadmap. You do.

Data migrations are where projects die. Splitting a shared database is the riskiest artifact in any decomposition: dual writes, backfills, consistency windows. AI can draft migration scripts, but a subtly wrong backfill corrupts production data in ways no test catches. Generated code that compiles or looks right while doing something different is annoying in application code and catastrophic in a migration.

Hallucination does not stop at the edge of your repo. A 2025 systematic review of code hallucinations explains why generated code can look right and still be wrong, including calls to things that do not exist. In greenfield code a hallucinated import fails fast. In a 15-year-old monolith, a plausible-sounding fabricated helper in a 900-line legacy class can survive review.

The workflow, phase by phase

Here is the sequence that keeps AI in its lane. It assumes a monolith with an automated build and a deployable facade position.

  1. Freeze the ground truth. Before any AI touches the code, capture current behavior: production metrics, key API contracts, and a set of manually verified golden scenarios. If the build takes an hour, fix that first; tools like Q Transform require a build and test cycle under 55 minutes for good reason.
  2. Build the comprehension map with AI, review it with humans. Run agentic analysis across the codebase: shared tables, call clusters, hidden couplings, the three modules everyone forgot. Treat the output as a hypothesis document, then have engineers who know the system mark it up. The disagreements are the valuable part.
  3. Choose one seam, small on purpose. Pick a bounded context with low blast radius first. Humans decide; AI's candidate list informs, not approves.
  4. Generate characterization tests, then curate them. Have AI draft the test harness around the seam, then hand-review every assertion. Watch for the trap: tests that faithfully lock in a legacy bug you actually want to fix on the other side. Fix the bug in the monolith first, then extract.
  5. Insert the facade, route gradually. Put the proxy in front and shift traffic behind feature flags. This step is nearly pure plumbing.
  6. Extract, shadow, compare, cut. Move the slice behind the facade, keep an anti-corruption layer at the boundary, and where data is involved, dual-write and compare outputs on shadow traffic before anything is authoritative. Only when the new service matches old behavior under real load do you delete the old path. Then pick the next seam and repeat.

Failure modes worth knowing by name

The distributed monolith: you extracted services that still call each other synchronously for every request, so you now have the old coupling plus network latency plus five deploy pipelines. The cure is boundary discipline, not more extraction.

Test theater: AI-generated suites that pass against the extracted service because they were generated from it. Characterization tests must be born on the legacy code and pass there first.

The hallucinated dependency: a generated refactor references a utility that does not exist or an internal library at the wrong version. Compilation catches some of these; integration tests catch the rest; nothing catches the ones nobody ran.

Premature data split: carving the database before the service boundary stabilizes forces a second migration. Keep the shared schema until the extracted service has proven its shape.

Trusting the summary: diff review and your own test run are the acceptance criteria, never the tool's self-assessment of what it changed.

The verdict

AI has genuinely changed the economics of monolith modernization, but only on the comprehension side. Mapping a codebase, proposing seams, and drafting the characterization test harness used to be the months-long pretext that killed these projects; they are now days. The judgment side, where to cut, how to split the data, what the business can tolerate, is unchanged and remains yours. The strangler fig is what makes the combination safe: every AI artifact gets validated against production behavior one small slice at a time. Architects who respect that division of labor ship decompositions. Architects who outsource the boundary decisions to a model ship distributed monoliths.

Decision rule: let AI map the code and draft the tests, and keep the boundary and data decisions with your architects. If a step decides where to cut or how to move the data, a human signs it off, and approval gates and permission modes keep an agent from acting before that happens.

Share this article

Related articles

Continue exploring similar guides and insights