Marcio Cunha

Giant monolith? How to migrate to microservices painlessly

Learn how to slice monolithic legacy applications using the Strangler Fig pattern to migrate to microservices incrementally, securely, and without downtime.

Marcio Cunha•5 min
Also available in:EspañolPortuguês
Summary
  • Incremental migration eliminates the high risk of rewriting entire systems from scratch all at once.
  • The Strangler Fig pattern intercepts monolith traffic and gradually redirects it to new services.
  • Temporarily maintaining a shared database requires strict synchronization strategies to prevent data corruption.
  • Reverse proxy tools act as the intelligent facade governing transparent request routing.
  • Decoupling business domains requires structural patience and constant measurement of latency and resource usage.

Why rewriting from scratch is the worst engineering trap

When a system grows continuously, it often turns into the infamous giant monolith: a massive tangle of code where everything is mixed together and any simple change can bring down the entire application. In theory, the temptation is to throw everything away and rewrite it from scratch using modern technologies. In practice, this approach usually backfires, consuming months of work, frustrating the team, and often delivering a brand new product full of the exact same old bugs. Instead of risking business operations on a drastic and blind change, modern engineering prefers a surgical and controlled transition, breaking the monster into smaller pieces gradually and painlessly.

To understand how this works in real life, imagine a complete renovation of an old house where people still live and work every day. You do not knock down the bedroom walls while someone is sleeping inside. You build a new room next to it, carefully connect the plumbing, and when everything is ready and tested, you transition the residents. In software architecture, the principle is exactly the same. This is where an elegant concept inspired by nature comes into play, perfect for those looking to understand more about microservices without global transactions and the Saga pattern, ensuring data consistency is maintained throughout the separation journey.

Understanding the Strangler Fig strategy

The technical name for this approach is the Strangler Fig Pattern. In the tropical rainforest, certain plants grow around the trunks of ancient trees, using their support to reach sunlight. Over the years, the fig tree grows so much that its roots choke and completely replace the original tree, which dies naturally without causing a sudden impact on the surrounding ecosystem. Applying this to software means building new microservices around the legacy monolith, absorbing its features one by one until the old system can be safely decommissioned.

In practice, this means you choose a specific and isolated feature from the current system, such as the invoicing module or user registration. You build this part from scratch using a modern, independent architecture. Next, you place an intelligent component in front of everything to decide who handles each call. If the request is for the new module, traffic goes to the microservice; if it is for anything else, it continues going to the old monolith. This way, the end user notices absolutely nothing, and the company keeps generating revenue normally while the engineering team modernizes the engine mid-flight.

How to intercept traffic without crashing the application

The operational secret of this migration lies in a reverse proxy, which acts as the intelligent doorman of your system. It receives all requests arriving from browsers or mobile apps and decides where to route them based on predefined rules. If your monolith responds to routes like api.my-store.com/v1/*, you can configure the proxy to send the specific route api.my-store.com/v1/payments to the new payments microservice, while everything else continues hitting the legacy code. This dynamic routing eliminates downtime, which is the period when the system goes offline and harms the business.

As the new microservice gains stability and undergoes rigorous testing in the production environment, the team expands the proxy rules to larger slices of the application. If any unexpected behavior or critical performance error occurs, you simply change the proxy rule back to the monolith in a matter of seconds, ensuring an instant rollback mechanism. This psychological safety net gives developers peace of mind to ship new code every day, knowing that any isolated failure will not compromise the overall stability of the company's technology platform.

The big challenge: handling the shared database

The biggest Achilles' heel during incremental migration is the database. In the monolith, all tables talk to each other freely, allowing complex queries that mix customer, order, and product data in the exact same SQL statement. When you split a piece of code into a microservice, the golden rule is that each microservice must have its own isolated database. However, cutting this umbilical cord overnight is almost impossible without breaking critical functionality that still relies on legacy data.

To solve this impasse painlessly, engineering usually adopts intermediate data transition phases. Initially, the new microservice can directly query the monolith database through views or read-only queries, while writes still pass through the legacy system. Next, asynchronous replication is implemented to synchronize data between the old database and the new isolated database. For complex integration scenarios, it is worth studying advanced strategies such as asynchronous synchronization using the Saga Pattern with Kafka, which guarantees eventual consistency between different services without freezing the system with pessimistic locks.

Step-by-step to slice the monolith safely

If you have a large system running in your company and need to start this transformation today, following a logical engineering sequence will save you a lot of headaches. Below is the practical procedure to start untangling your monolith using the Strangler Fig pattern: To explore these architectural concepts further in production, see our related technical analysis on AI creating malicious code? How to block bugs and exploits.

  1. Map business domain boundaries using Domain-Driven Design techniques to identify which microservice should be extracted first.
  2. Configure a modern reverse proxy, such as Nginx or Caddy, at the edge of your infrastructure to manage traffic routing.
  3. Build the new microservice in isolation, ensuring robust automated tests and centralized logs for observability.
  4. Redirect a small percentage or specific traffic route using the proxy to validate behavior in production.
  5. Gradually decouple the data layer and decommission the corresponding legacy code in the monolith after confirming total stability.

Final thoughts on the journey toward microservices

Migrating from a giant monolith to microservices is not just a technology project, but an evolution in how engineering delivers value to the business. The Strangler Fig pattern turns a Herculean and terrifying task into small daily victories, where each delivery brings learning, stability, and confidence to the team. Haste in eliminating legacy code usually breeds chaos, but strategic patience combined with modern proxy and observability tools ensures a smooth and painless transition.

At the end of the day, the ideal architecture is not the one using this week's trendiest technology, but the one that allows your company to grow, fail safely, and adjust its course without stopping service to customers. By slicing the monolith incrementally, you protect the company's current revenue while building solid foundations for future innovation.