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
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:
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 B
Step-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:
Examples:
Authentication
Notifications
Reporting
Payments
Step 3: Create a New ASP.NET Core Microservice
Create a new project:
dotnet new webapi -n NotificationService
This service should:
Step 4: Route Traffic Using an API Gateway
Use tools like:
Example with YARP:
This makes the migration invisible to clients.
Step 5: Data Management Strategy
Avoid sharing databases.
Common approaches:
Never let microservices directly access the monolith database.
Step 6: Communication Between Monolith and Microservices
Preferred methods:
Example:
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
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.