All Playbooks
Architectureadvanced

Migrating a Monolith to Microservices

Most monolith-to-microservices stories end as cautionary tales because the team tried to design the future architecture instead of evolving toward it. This playbook is the staged migration I run: map the domain, find natural seams, extract behind a stable façade, adopt event-driven communication where it pays off, and decommission the old system gradually. Boring, slow, and the only version that consistently works.

180 min8 steps
8

Steps

5

Tools

5

Outcomes

advanced

Difficulty

Technologies used

Node.jsPostgreSQLKafkaKubernetesOpenTelemetry

The methodology

The phases, in order

Each phase below is something I actually run in a project. The descriptions are how I think about the work, not abstract definitions.

01

Phase

Phase 1 of 8

Audit the Monolith Honestly

Before any extraction I map the modules, the data flows, the deploy frequency, and the team ownership. Heat maps tell you which areas change most and where coordination costs are highest. Those areas are usually the right places to split first, regardless of how clean the boundaries look on paper.
02

Phase

Phase 2 of 8

Identify Bounded Contexts

I use domain-driven design to find natural seams: places where the language, data, and rules genuinely differ. A bounded context is not a CRUD entity, it is a chunk of the business that could plausibly be run by one team. Anything smaller is premature, anything larger is just a smaller monolith.
03

Phase

Phase 3 of 8

Stand Up a Strangler Façade

All traffic routes through a façade, usually an API gateway or a thin proxy. This lets me swap the implementation behind a route without coordinating client changes. The façade also becomes the place where authentication, rate limiting, and versioning live, which is useful long after the migration is over.
04

Phase

Phase 4 of 8

Extract the First Service

The first extraction is always a low-risk domain with clean boundaries: notifications, reporting, search. Goal one is to prove the deployment, observability, and operational story end to end. Goal two is to build team muscle memory. The actual scope of the first service is intentionally small.
05

Phase

Phase 5 of 8

Adopt Event-driven Communication

Synchronous service-to-service calls are how you turn a monolith into a distributed monolith. Async events through Kafka or an equivalent broker let services evolve independently. See the event-driven systems playbook for the patterns.
06

Phase

Phase 6 of 8

Observability and Tracing First

Before extracting the second service I make sure distributed tracing, structured logs, and per-service metrics work end to end. Debugging a microservice system without those is genuinely impossible. See monitoring for the full stack.
07

Phase

Phase 7 of 8

Data Ownership and Migration

Each service owns its data. Cross-service reads happen through APIs or events, never direct database access. For tables that need to move, I run dual writes and a backfill until the new service is canonical, then cut over reads. No shared databases survive the migration.
08

Phase

Phase 8 of 8

Decommission the Monolith

Decommissioning is gradual: each successful extraction shrinks the monolith. I delete code aggressively, route by route, and resist the urge to keep an old code path warm just in case. The migration is done when the old monolith is small enough to be a microservice itself.

Results

What You'll Achieve

Expected outcomes from implementing this playbook

Independently deployable services with clean ownership
Reduced blast radius for changes and easier rollbacks
Improved team autonomy without coordination tax
Better scaling characteristics on the hot paths
Need a migration partner? Architecture review or contact me.

Use this playbook

Want me to run this with you?

The playbook is the public version. The private version is me running it for your team against a real deadline. If you have a project on the line, that is usually the faster path.