Introduction
Microservices architecture has become the preferred approach for building scalable, maintainable, and cloud-native applications. However, most real-world systems do not start as microservices. They start as monolithic applications, often built years ago, running critical business logic.
A common misconception is that adopting microservices requires a complete rewrite. In reality, rewriting a monolith from scratch is risky, expensive, and rarely successful.
This article explains how to build microservices via an existing monolith in .NET Core, using a safe and proven migration strategy known as the Strangler Fig Pattern.
What Is a Monolithic Application?
A monolith is an application where:
All features live in a single codebase
Components are tightly coupled
Deployment happens as one unit
Challenges of a Monolith
Slow deployments
Difficult scaling
High risk when changing code
Hard to adopt new technologies
Despite these challenges, monoliths are not “bad”. They are often stable and business-critical, which is why careful evolution is needed.
Why Not Rewrite Everything as Microservices?
A full rewrite introduces:
Business downtime
Loss of domain knowledge
New bugs and regressions
Long time-to-market
Instead of replacing the monolith, a gradual migration is the safest approach.
What Does “Microservices via Monolith” Mean?
“Microservices via Monolith” means:
Keeping the existing monolith alive
Gradually extracting features into microservices
Letting both systems coexist during the transition
This approach allows teams to:
Reduce risk
Deliver value incrementally
Learn microservices without breaking production
The Strangler Fig Pattern
The Strangler Fig Pattern is a migration strategy where:
New features are built as microservices
Existing functionality is slowly moved out
The monolith eventually becomes obsolete
Named after the strangler fig tree, which grows around an existing tree until it replaces it.
High-Level Architecture
Client
|
API Gateway / Reverse Proxy
|
----------------------------
| | |
Monolith Microservice A Microservice BStep-by-Step Migration in .NET Core
Step 1: Modularize the Monolith
Before extracting services, clean up the monolith:
Separate business logic from controllers
Use layered architecture (API, Application, Domain, Infrastructure)
Identify bounded contexts
Tip: If your monolith is already in ASP.NET Core, you are halfway there.
Step 2: Identify a Candidate Microservice
Good candidates:
Low coupling with other modules
Clear business boundaries
High change frequency
Examples:
Authentication
Notifications
Reporting
Payments
Step 3: Create a New ASP.NET Core Microservice
Create a new project:
dotnet new webapi -n NotificationServiceThis service should:
Own its database
Expose REST APIs
Be independently deployable
Step 4: Route Traffic Using an API Gateway
Use tools like:
YARP (Yet Another Reverse Proxy)
Ocelot
Azure API Management
Example with YARP:
/api/notifications→ Microservice/api/orders→ Monolith
This makes the migration invisible to clients.
Step 5: Data Management Strategy
Avoid sharing databases.
Common approaches:
Database per service
Data synchronization via events
Read replicas for legacy data
Never let microservices directly access the monolith database.
Step 6: Communication Between Monolith and Microservices
Preferred methods:
REST APIs
Asynchronous messaging (RabbitMQ, Azure Service Bus)
Example:
Monolith publishes
OrderCreatedeventMicroservice listens and processes it
Example: Extracting Notification Service
Before (Monolith)
public class OrderService
{
public void CreateOrder()
{
// Order logic
SendEmail();
}
}After (Microservice)
// Monolith
PublishEvent(new OrderCreatedEvent());
// Notification Microservice
public class OrderCreatedHandler
{
public Task Handle(OrderCreatedEvent evt)
{
SendEmail();
}
}Result:
Loose coupling
Independent scaling
Faster deployments
Benefits of Microservices via Monolith
✔ Lower migration risk
✔ Continuous delivery
✔ Independent scaling
✔ Better maintainability
✔ Cloud readiness
Common Mistakes to Avoid
❌ Extracting too many services at once
❌ Sharing databases
❌ Overusing synchronous calls
❌ Ignoring observability (logs, metrics, tracing)
Tools Commonly Used in .NET Core Microservices
ASP.NET Core
Docker
Kubernetes
YARP / Ocelot
Serilog
OpenTelemetry
RabbitMQ / Azure Service Bus
When Should You Stop?
The migration ends when:
The monolith no longer handles business logic
Remaining code is minimal or retired
All core features live in microservices
At this point, the monolith can be safely decommissioned.
Conclusion
Migrating from a monolith to microservices does not require a risky rewrite. By using the Microservices via Monolith approach with .NET Core and the Strangler Fig Pattern, teams can modernize their applications safely, incrementally, and confidently.
This strategy is battle-tested, production-friendly, and ideal for organizations that want the benefits of microservices without the pain of starting over.

Join the conversation! Your thoughts help the community grow.