.NET Core  

Microservices via Monolith in .NET Core

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:

  1. New features are built as microservices

  2. Existing functionality is slowly moved out

  3. 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:

  • 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 NotificationService

This 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 OrderCreated event

  • Microservice 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.