From monolith to modular: A pragmatic migration strategy
The rewrite trap
The most dangerous sentence in software engineering is: "Let's rewrite it from scratch." Rewrites are attractive because they promise a clean slate. In practice, they almost always take longer than expected, deliver less than promised, and risk the business during the transition.
A better approach is incremental migration: replacing parts of the monolith one piece at a time while keeping the system running.
The strangler fig pattern
Named after the strangler fig tree that grows around a host tree and eventually replaces it, this pattern involves wrapping the monolith with a new facade and gradually replacing internal components with new services.
The key steps:
- Identify a seam. Find a boundary in the monolith where you can intercept requests. This might be an API gateway, a specific module, or a database table.
- Build the new component. Implement the replacement as a standalone service with its own data store.
- Route traffic. Direct requests for that component to the new service while keeping everything else in the monolith.
- Remove the old code. Once the new service is stable and all traffic is routed to it, delete the corresponding code from the monolith.
Domain-Driven Design as a guide
Domain-Driven Design helps you identify the right seams. Bounded contexts — areas of the business with distinct rules and language — natural boundaries for extraction.
We start with event storming workshops to map the business domain. This surfaces bounded contexts, aggregate roots, and domain events that inform both the service boundaries and the API contracts between them.
Keeping the business running
The critical advantage of incremental migration is that the business never stops. Customers do not notice the transition. Revenue continues flowing. The team learns and adapts without the pressure of a hard deadline.
This approach requires patience and discipline. It is slower than a big-bang rewrite, but it is far more likely to succeed.