Sức mạnh của Monolith (đơn giản, strong consistency) kết hợp tổ chức code kiểu Microservices (module độc lập). Con đường tiến hóa tự nhiên nhất từ Monolith sang Microservices.
Tổng Quan
Key Point: 1 Deployment, NHIỀU modules, mỗi module có schema riêng trong cùng DB. Modules giao tiếp qua Integration Events, KHÔNG gọi trực tiếp internal services của nhau.
Khi Nào Dùng / Không Dùng
| ✅ Dùng khi | ❌ Không dùng khi |
|---|---|
| Team 5-15 devs, growing | Solo dev hoặc < 3 devs |
| Muốn chuẩn bị cho future Microservices | Đã cần scale từng service RIÊNG BIỆT |
| Domain phức tạp, nhiều bounded contexts | Simple CRUD, 1 bounded context |
| Cần strong consistency nhưng muốn module isolation | Đã có DevOps mature cho k8s |
Dự án hay dùng: SaaS products, ERP, eCommerce giai đoạn growth, Insurance platforms.
Project Structure
MyApp/
├── MyApp.sln
├── src/
│ ├── Bootstrapper/
│ │ └── MyApp.Host/ ← Single entry point
│ │ ├── Program.cs
│ │ └── appsettings.json
│ │
│ ├── Shared/
│ │ └── MyApp.Shared/ ← Shared Kernel
│ │ ├── Abstractions/
│ │ │ ├── IIntegrationEvent.cs
│ │ │ └── IModule.cs
│ │ └── Contracts/ ← Shared DTOs (inter-module)
│ │ └── OrderCreatedIntegrationEvent.cs
│ │
│ ├── Modules/
│ │ ├── Orders/
│ │ │ ├── MyApp.Modules.Orders.Domain/
│ │ │ ├── MyApp.Modules.Orders.Application/
│ │ │ ├── MyApp.Modules.Orders.Infrastructure/
│ │ │ └── MyApp.Modules.Orders.API/
│ │ │ └── OrdersModule.cs ← IModule implementation
│ │ │
│ │ ├── Inventory/
│ │ │ ├── MyApp.Modules.Inventory.Domain/
│ │ │ ├── MyApp.Modules.Inventory.Application/
│ │ │ ├── MyApp.Modules.Inventory.Infrastructure/
│ │ │ └── MyApp.Modules.Inventory.API/
│ │ │
│ │ └── Shipping/
│ │ └── ... (same structure)
│ │
└── tests/
├── Modules/
│ ├── Orders.Tests/
│ └── Inventory.Tests/
└── Integration/
└── ModuleCommunication.Tests/
Module Registration & Isolation
csharp// Shared/IModule.cs
public interface IModule
{
void RegisterServices(IServiceCollection services, IConfiguration config);
void MapEndpoints(IEndpointRouteBuilder app);
}
// Orders/OrdersModule.cs
public class OrdersModule : IModule
{
public void RegisterServices(IServiceCollection services, IConfiguration config)
{
services.AddDbContext<OrdersDbContext>(o =>
o.UseSqlServer(config.GetConnectionString("Default"),
sql => sql.MigrationsHistoryTable("__EFMigrationsHistory", "orders")));
// ↑ Schema riêng "orders" - isolation ở DB level
services.AddMediatR(cfg =>
cfg.RegisterServicesFromAssembly(typeof(OrdersModule).Assembly));
}
public void MapEndpoints(IEndpointRouteBuilder app)
{
var group = app.MapGroup("/api/orders").WithTags("Orders");
group.MapPost("/", CreateOrder.Handle);
group.MapGet("/{id}", GetOrderById.Handle);
}
}
// Host/Program.cs - Auto-discover modules
var modules = DiscoverModules(); // Scan assemblies for IModule
foreach (var module in modules)
module.RegisterServices(builder.Services, builder.Configuration);
var app = builder.Build();
foreach (var module in modules)
module.MapEndpoints(app);
Module Communication (Integration Events)
csharp// KHÔNG gọi InventoryService trực tiếp!
// ❌ var inventory = _inventoryService.ReserveStock(productId, qty);
// ✅ Publish Integration Event
await _mediator.Publish(new OrderCreatedIntegrationEvent(order.Id, order.ProductId, order.Quantity));
Tiến hóa → Microservices
Khi module X cần scale riêng:
1. Extract module X ra standalone service
2. Thay In-Process Event Bus → Message Broker (RabbitMQ/Azure Service Bus)
3. Tách database schema ra DB riêng
→ Module code gần như KHÔNG ĐỔI (chỉ đổi infra wiring)