Cuando hablamos de arquitecturas en .NET, el debate siempre se va al extremo: o tienes un monolito gigante imposible de mantener, o te lanzas de cabeza a los microservicios, con todo lo que eso implica (infraestructura, autenticación distribuida, resiliencia, logging centralizado...).
Pero hay una opción intermedia que muchas veces se subestima: el Monolito Modular.
Y con .NET 8, ¡es más fácil que nunca implementarlo!
🔍 ¿Qué es un Monolito Modular?
Un Modular Monolith es una única aplicación desplegable, pero organizada internamente en módulos bien definidos. Cada módulo representa una funcionalidad o dominio del negocio, y se comunica con otros usando interfaces o eventos internos. No hay dependencias cruzadas, y cada módulo puede evolucionar de forma independiente.
Es decir: estructura limpia, despliegue simple.
🧰 ¿Cómo implementarlo en .NET 8?
Aquí algunos pilares para organizar un Monolito Modular con herramientas modernas:
1. 🗂 Estructura de solución
Organiza tu solución en proyectos por módulo:
/src
/Modules
/Customers
Customers.API.csproj
Customers.Application.csproj
Customers.Domain.csproj
Customers.Infrastructure.csproj
/Orders
Orders.API.csproj
Orders.Application.csproj
Orders.Domain.csproj
Orders.Infrastructure.csproj
WebGateway.csproj (el host principal)
Cada módulo se estructura con un enfoque DDD + Clean Architecture, y el proyecto principal (WebGateway) referencia a los módulos mediante ProjectReference.
2. ✉️ Comunicación entre módulos
Usa MediatR para manejar la comunicación desacoplada entre capas (o incluso entre módulos, si lo encapsulas bien).
// Customers.Application
public record GetCustomerByIdQuery(Guid Id) : IRequest<CustomerDto>;
// Customers.Application.Handlers
public class GetCustomerByIdHandler : IRequestHandler<GetCustomerByIdQuery, CustomerDto>
{
// lógica para obtener cliente
}
Y desde otro módulo (como Orders), puedes inyectar IMediator y lanzar el query, sin acoplarte directamente.
3. 🚪 Exposición de Endpoints
Cada módulo puede tener sus propios endpoints definidos como Minimal APIs y registrados en el Program.cs principal:
// Customers.API
public static class CustomerEndpoints
{
public static IEndpointRouteBuilder MapCustomerEndpoints(this IEndpointRouteBuilder endpoints)
{
endpoints.MapGet("/customers/{id}", async (Guid id, IMediator mediator) =>
{
var customer = await mediator.Send(new GetCustomerByIdQuery(id));
return Results.Ok(customer);
});
return endpoints;
}
}
Y en Program.cs:
app.MapCustomerEndpoints();
app.MapOrderEndpoints();
4. 🧪 Testing más fácil
Cada módulo puede tener su propio proyecto de pruebas unitarias y de integración, enfocado en su lógica de negocio. Esto te da alta cohesión y bajo acoplamiento.
✅ Beneficios reales en .NET
-
Un solo despliegue (ideal para Azure App Services, contenedores, IIS, etc.)
-
Modularidad para equipos grandes
-
Facilidad de testing, mantenimiento y refactorización
-
Puedes migrar módulos individuales a microservicios sin reescribir todo
🚀 ¿Cuándo usar esta arquitectura?
Un Monolito Modular en .NET 8 es ideal cuando:
-
Estás construyendo una app empresarial (ERP, CRM, Portales internos, etc.)
-
Quieres mantener la simplicidad del monolito pero sin comprometer la escalabilidad del código.
-
Tienes un equipo que trabaja por módulos funcionales.
-
Planeas evolucionar gradualmente hacia microservicios.
🧩 Recursos adicionales
-
📖 Artículo base: What is a Modular Monolith?
-
📘 Recomendado: Modular Monoliths – Kamil Grzybek