Monolith to MicroservicesMS-05 · theory

Source · Newman, Monolith to Microservices (O'Reilly); Newman, Building Microservices 2e (O'Reilly)

Why this matters

Newman, Monolith to Microservices, Ch. 1-3

Most microservices work is not greenfield; it is extracting services from an existing monolith that the business depends on daily. A big-bang rewrite is notoriously risky - it freezes feature delivery for months and often fails. The value of migration patterns is that they let you move incrementally, delivering and de-risking in small steps while the old system keeps running.

Understanding these patterns matters because the hardest part of the migration is rarely the code; it is the data. Splitting a shared database while keeping the system correct and consistent is where migrations succeed or stall, so the patterns focus heavily on decoupling data safely.

The concept

Newman, Monolith to Microservices, Ch. 3-4 (Splitting the database; Growing pains)

The signature pattern is the strangler fig (named after the vine that grows around a tree and gradually replaces it). You place a proxy or gateway in front of the monolith and incrementally intercept calls: functionality you have re-implemented as a new service is routed to it, while everything else still flows to the monolith. Over time more paths move across until the monolith can be retired. Crucially, you can roll back a single route if the new service misbehaves.

Decomposition strategy starts from bounded contexts and business capabilities: identify a seam - a cohesive slice with a clear boundary and limited data entanglement - and extract it first, favoring low-risk, high-value candidates.

Database decomposition is the crux. Because services must own their data, you must untangle shared tables. Patterns include splitting the database before or after splitting the code, using a shared database only as a transitional step, and techniques like the database view, database wrapping service, and change-data-capture to let the new service own its data while the monolith is weaned off. During transition you may temporarily keep two copies in sync and accept eventual consistency.

Other migration patterns include branch by abstraction (introduce an abstraction in the monolith, build the new implementation behind it, then switch over) and parallel run (run old and new side by side, comparing results before trusting the new path).

Worked scenario

Newman, Monolith to Microservices, Ch. 3 (Strangler fig, branch by abstraction, parallel run)

A monolith handles user accounts, notifications, and billing against one shared database. The team wants to extract Notifications first because it is cohesive and low-risk.

They put a gateway in front of the monolith (the strangler fig). They build a new Notifications service, but its data still lives in shared tables that billing also reads. Rather than a risky simultaneous split, they use branch by abstraction inside the monolith to route notification logic to the new service, and they decompose the data by giving Notifications its own store, back-filling it and keeping it in sync via change-data-capture during transition. They run the old and new notification paths in parallel, comparing outputs, until confident. Then the gateway routes all notification traffic to the new service, the old code is deleted, and the shared tables it used are retired.

No feature freeze, each step reversible, and the riskiest part - the data - handled with an explicit transitional strategy rather than a big-bang cutover.

How it connects

Newman, Monolith to Microservices, Ch. 5 (Growing pains); Building Microservices 2e, Ch. 3

Migration is the fundamentals applied in reverse-motion: you are manufacturing independent deployability and data ownership where none existed. The bounded contexts from the fundamentals become your decomposition seams. The strangler fig lives at the API gateway from the API topic, and the transitional data sync leans on the event-driven and eventual-consistency ideas - change-data-capture is itself an event stream of database changes.

The overarching lesson ties back to the whole path: migrate incrementally, extract services only where a concrete driver justifies it, and treat data decomposition as the central challenge. Done well, you reach the autonomy microservices promise without betting the business on a single rewrite.

Common traps
  • Planning a big-bang rewrite. It freezes delivery and is high-risk; the patterns exist precisely to migrate incrementally and reversibly.
  • Underestimating data decomposition. Splitting shared tables - not moving code - is the hardest part, and skipping a transitional data strategy causes correctness and consistency failures.
  • Confusing the strangler fig with a rewrite. The strangler fig intercepts and incrementally reroutes calls around the running monolith; it does not replace everything at once.
Key takeaways
  • The strangler fig fronts the monolith with a proxy and incrementally reroutes functionality to new services, keeping each step reversible and avoiding a feature freeze.
  • Decompose by bounded context, extracting cohesive, low-risk seams first; database decomposition (views, wrapping services, change-data-capture) is the central challenge.
  • Techniques like branch by abstraction and parallel run let you build and validate new services safely before switching traffic over.