Skip to main content

Command Palette

Search for a command to run...

From Monolith to Microservices Using The Strangler Fig Pattern

Updated
5 min read
From Monolith to Microservices Using The Strangler Fig Pattern
P
Senior Software Engineer specialising in cloud architecture, distributed systems, and modern .NET development, with over two decades of experience designing and delivering enterprise platforms in financial, insurance, and high-scale commercial environments. My focus is on building systems that are reliable, scalable, and maintainable over the long term. I’ve led modernisation initiatives moving legacy platforms to cloud-native Azure architectures, designed high-throughput streaming solutions to eliminate performance bottlenecks, and implemented secure microservices environments using container-based deployment models and event-driven integration patterns. From an architecture perspective, I have strong practical experience applying approaches such as Vertical Slice Architecture, Domain-Driven Design, Clean Architecture, and Hexagonal Architecture. I’m particularly interested in modular system design that balances delivery speed with long-term sustainability, and I enjoy solving complex problems involving distributed workflows, performance optimisation, and system reliability. I enjoy mentoring engineers, contributing to architectural decisions, and helping teams simplify complex systems into clear, maintainable designs. I’m always open to connecting with other engineers, architects, and technology leaders working on modern cloud and distributed system challenges.

Migrating from a monolithic architecture to microservices is a daunting task. One of the most effective strategies to make this transition smoother is the Strangler Fig Pattern. This pattern allows gradual replacement of monolithic components with microservices while keeping the system functional throughout the transition. In this article, we'll explore what the Strangler Fig pattern is, why it's beneficial, and how to implement it in your migration journey.

What is the Strangler Fig Pattern?

The Strangler Fig Pattern is inspired by the way strangler fig trees grow around existing trees, eventually replacing them. Applied to software architecture, this pattern suggests replacing a monolithic system incrementally by creating new microservices that intercept and gradually take over functionalities, leaving the monolith to shrink over time.

Instead of rewriting the entire system from scratch, a high risk approach, the Strangler Fig pattern lets you migrate one piece at a time, reducing downtime and allowing for continuous delivery.

Why Use the Strangler Fig Pattern?

  1. Incremental Transition – Instead of a full rewrite, you replace components step by step.

  2. Reduced Risk – Since the monolith remains operational, failures in microservices do not break the entire system.

  3. Faster Time to Market – Teams can deliver new microservices iteratively without waiting for a complete migration.

  4. Better Testing and Debugging – You can validate new microservices in production without affecting existing functionality.

  5. Minimal User Impact – Users continue interacting with the system without noticing major changes.

Steps to Implement the Strangler Fig Pattern

1. Identify Monolithic Components for Extraction

Start by analysing the monolith and identifying the most suitable components to extract first. Ideal candidates include:

  • Services with high scalability needs

  • Frequently changing functionalities

  • Well-defined domain boundaries (e.g., authentication, payments, or reporting)

2. Introduce a Proxy or API Gateway

To transition smoothly, introduce an API Gateway or proxy that will act as an intermediary between clients and the monolith. This allows traffic to be directed to either the monolith or the new microservices.

  • Initially, all requests route to the monolith.

  • As microservices are introduced, specific requests can be redirected accordingly.

  • Over time, the monolith handles fewer and fewer requests.

3. Develop and Deploy Microservices

For each selected monolithic component:

  • Extract the logic into a new microservice.

  • Deploy the microservice independently.

  • Modify the API Gateway to route relevant requests to the microservice.

4. Data Migration Strategy

Decide how microservices will handle data:

  • Database per service: Each microservice manages its own data.

  • Read/Write Split: The monolith remains the source of truth while microservices handle reads.

  • Change Data Capture (CDC): Microservices listen to database changes in the monolith to stay in sync.

5. Decommission Old Monolith Components

Once a microservice fully replaces a monolithic function:

  • Monitor and validate performance.

  • Disable the monolithic code handling that function.

  • Continue this process iteratively until the monolith is completely phased out.

6. Optimise and Scale

As more microservices replace monolithic features:

  • Optimise them for scalability, resilience, and observability.

  • Implement logging, monitoring, and distributed tracing.

  • Ensure CI/CD pipelines facilitate smooth deployments.

Real World Example: E-commerce Platform Migration

Consider an e-commerce platform with a monolithic architecture handling user management, orders, and payments. Using the Strangler Fig pattern:

  1. An API Gateway is introduced.

  2. The user management module is extracted as the first microservice.

  3. Requests related to users are routed to the new microservice while the rest hit the monolith.

  4. Once validated, the monolithic user management logic is retired.

  5. The process repeats for orders and payments until the entire monolith is replaced.


Optional - Modular Monolith as a Transitional Phase

Transitioning from a traditional monolith to a microservices architecture can be complex and risky if undertaken as a complete rewrite. A modular monolith can serve as a crucial intermediate step, allowing an application to evolve in a controlled manner. Instead of immediately introducing distributed systems complexity, this phase focuses on internal modularisation while retaining the benefits of a single deployable unit.

A modular monolith maintains a single codebase and deployment, but its internal structure is redesigned to enforce clear separation of concerns through well defined modules. Each module encapsulates a specific bounded context, following principles from Domain Driven Design (DDD). Unlike a traditional monolith, where components often share direct dependencies and a common database, a modular monolith minimises tight coupling by enforcing strict internal APIs or domain-driven contracts between modules. This ensures that modules interact in a controlled manner rather than through arbitrary shared state.

One of the key advantages of a modular monolith is that it enables incremental extraction of microservices when needed. By ensuring that each module is functionally independent, teams can gradually transition individual modules into standalone services. This can be achieved by introducing internal APIs that mimic how these modules would communicate as microservices in the future. Initially, these APIs may operate as simple method calls within the monolith, but as migration progresses, they can be converted into network-based service calls without disrupting the rest of the system.

Another crucial benefit of a modular monolith is its ability to improve team autonomy while avoiding premature operational complexity. Many developers that move too quickly to microservices encounter challenges related to deployment orchestration, service discovery, distributed data management, and observability. A modular monolith provides a low risk environment where teams can practice modular design principles, introduce event-driven communication, and even experiment with techniques like CQRS and eventual consistency before introducing the full complexity of microservices.

By adopting a modular monolith, developers gain better maintainability, improved scalability, and a clearer migration path toward microservices. It allows for gradual evolution rather than a disruptive rewrite, ensuring that the system can be optimised for modularity first, before making the leap to full service decomposition.

Migrating from a monolith to microservices is complex, but the Strangler Fig pattern makes it manageable. By incrementally replacing monolithic functionalities, you reduce risk, improve maintainability, and ensure business continuity throughout the transition.