Migrating to Microservices: EShop Modules to Microservices with the Strangler Fig Pattern🌳➡️📦

Mehmet Ozkaya
5 min readSep 4, 2024

--

Refactoring a monolithic application into microservices is a significant undertaking, but with the right strategy, it can be a smooth and rewarding process.

Migrate to Microservices: EShop Modules to Microservices

Get Udemy Course with limited discounted coupon — .NET Backend Bootcamp: Modulith, VSA, DDD, CQRS and Outbox

In this article, we will explore how to apply the Strangler Fig Pattern to migrate EShop modules to microservices. We’ll break down the migration process into eight key steps, each designed to help you transition effectively without disrupting your existing application.

Steps of Refactoring Monolith into Microservices

Migrating from a monolithic architecture to microservices involves several important steps. Let’s dive into each one to understand the process better:

Steps of Refactoring Monolith into Microservices

Step 1: Decompose EShop Modules into Microservices with DDD Bounded Contexts 📦

Identify Bounded Contexts:

  • The first step is to analyze the existing monolithic application and identify bounded contexts within the domain.
  • For the EShop application, modules such as Catalog, Basket, Ordering, and Identity represent distinct bounded contexts.

Define Service Boundaries:

  • Define clear boundaries for each microservice based on these identified bounded contexts.
  • Each service should encapsulate a specific business capability and manage its own data independently.
EShop Modules Decomposed into Microservices with DDD Bounded Contexts

Step 2: Prioritize Modules-Services for Migration 🥇

Assess Module Complexity:

  • Evaluate the complexity of each module and its dependencies.
  • Start by migrating less complex, highly decoupled modules first to build confidence and gain experience.

Business Impact:

  • Prioritize modules that have a significant impact on the business and user experience.
  • This ensures that the most valuable parts of the application are migrated early, maximizing business benefits.
Image: Prioritizing “Identity” Module for Migration

Step 3: Extract a Service from a Monolith 🛠️

Isolate Code and Data:

  • Extract the code and data related to the chosen module from the monolithic application.
  • Ensure that the newly extracted service can function independently without relying on the monolith.

Create APIs:

  • Develop APIs for the extracted service to interact with other services and the remaining monolith during the transition phase.
  • Ensure backward compatibility to avoid disruptions for existing users.
Extracting “Identity” as a Service from the Monolith

Step 4: Manage a Monolithic Database 🗄️

Database Decomposition:

  • Gradually decompose the monolithic database into smaller, service-specific databases.
  • Use strategies like database replication, shared databases with schema separation, or eventual consistency to manage data across services.

Data Synchronization:

  • Implement data synchronization mechanisms to keep data consistent across services during the transition period.
  • Techniques like Change Data Capture (CDC) or Event Sourcing can be used for real-time data updates.
Decomposing “Identity” Schema to a Separate PostgreSQL Database

Step 5: Design and Implement Interservice Communication 📡

Synchronous Communication:

  • Use RESTful APIs or gRPC for synchronous communication between services.
  • Design APIs with clear contracts and versioning to ensure compatibility over time.
Current State: Modular Monolithic w/ Contracts

The above diagram evolves REST APIs when migrating to microservices:

Evolving Sync Communication to Microservices HTTP Calls

Step 6: Async Communication Between Services 🔄

Asynchronous Communication:

  • Implement message brokers like RabbitMQ or Kafka for asynchronous communication.
  • Use events and message queues to decouple services and enhance resilience.

Event-Driven Architecture:

  • Design services to publish and subscribe to events using an event-driven architecture.
  • This approach enhances decoupling and allows services to react to changes asynchronously, improving scalability.

Eventual Consistency:

  • Embrace eventual consistency for data synchronization across services.
  • Ensure services can handle data inconsistencies gracefully and resolve them over time.
Microservices Async Communication w/ RabbitMQ & MassTransit

Step 7: Distributed Transactions and Data Consistency 🔍

Saga Pattern:

  • Implement the Saga Pattern to manage distributed transactions across multiple services.
  • Design compensating transactions to handle failures and ensure data consistency.

Outbox Pattern:

  • Use the Outbox Pattern to reliably publish events as part of the transaction that updates the database.
  • This ensures that events are only published if the transaction commits successfully, maintaining data integrity.
Outbox Pattern For Reliable Messaging

Step 8: Deployment of Microservices after Monolithic 🚀

Containerization:

  • Containerize each microservice using Docker to ensure consistent deployment environments.
  • Use Kubernetes for orchestration and scaling of containers across multiple environments.

Continuous Integration and Continuous Deployment (CI/CD):

  • Implement CI/CD pipelines to automate the build, test, and deployment processes.
  • Ensure that each service can be deployed independently and rolled back if necessary.

Monitoring and Logging:

  • Implement comprehensive monitoring and logging solutions to track the performance and health of each service.
  • Use tools like Prometheus, Grafana, ELK Stack, or Jaeger for observability and troubleshooting.
Deploying Microservices After Monolithic Transformation

Conclusion 🎯

Migrating from a monolithic architecture to microservices is a complex but rewarding process. By following best practices, leveraging domain-driven design, and adopting an incremental approach like the Strangler Fig Pattern, you can ensure a smooth transition.

Migrate to Microservices: EShop Modules to Microservices

We will delve deeper into each step, providing practical examples and strategies to help you successfully migrate your monolithic application to a microservices-based architecture. So, let’s start this exciting journey of transformation and modernization! 🚀🌟

Get Udemy Course with limited discounted coupon — .NET Backend Bootcamp: Modulith, VSA, DDD, CQRS and Outbox

EShop Modular Monoliths Architecture w/ Catalog, Basket, Identity and Ordering modules

This is step-by-step development of reference Modular Monoltihs Architecture on .NET used ASP.NET Web API, Docker, PostgreSQL, Redis, RabbitMQ, Keycloak, Seq, MassTransit, Entity Framework Core, CQRS, MediatR, DDD, Vertical Slice Architecture and Outbox Pattern implementation with using latest features of .NET 8 and C# 12.

--

--

Mehmet Ozkaya

Software Architect | Udemy Instructor | AWS Community Builder | Cloud-Native and Serverless Event-driven Microservices https://github.com/mehmetozkaya