.png)
¿Alguna vez has sentido que tu proyecto es demasiado grande para un monolito, pero demasiado pequeño para la complejidad operativa de los microservicios? Quizás te has visto forzado a dividir tu código en múltiples repositorios solo para poder escalar una parte específica del sistema.
En el desarrollo de software moderno, existe un punto medio estratégico: la Arquitectura Modular dirigida por perfiles. Este enfoque permite que la topología de despliegue sea simplemente una decisión de configuración en tiempo de ejecución, eliminando la fricción técnica innecesaria.
Para demostrarlo, exploraremos ModularMS, un proyecto que ejemplifica cómo este modelo permite transitar entre diferentes arquitecturas sin reescribir una sola línea de lógica de negocio.
Normalmente, el camino de escalabilidad es rígido: se inicia con un monolito y se "evoluciona" hacia microservicios mediante una reescritura masiva. Sin embargo, este paso suele traer consigo el "impuesto" de la complejidad distribuida.
Con la propuesta de ModularMS, los módulos son la unidad de diseño primaria y el despliegue es solo una opción. El mismo código puede adaptarse a tres escenarios distintos:
1. Monolito Modular: Todos los módulos residen en una sola instancia, ideal para equipos pequeños o etapas iniciales.
┌────────────────────────────────────┐
│ Aplicación │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │Módulo A│ │Módulo B│ │Módulo C│ │
│ └────────┘ └────────┘ └────────┘ │
└────────────────────────────────────┘
2. Microservicios Independientes: Una instancia independiente por cada módulo para escalabilidad granular.
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Módulo A │ │ Módulo B │ │ Módulo C │
│ Servicio │ │ Servicio │ │ Servicio │
└────────────┘ └────────────┘ └────────────┘
3. Microservicios Agrupados: Módulos relacionados compartiendo el mismo despliegue, optimizando el uso de recursos.
┌──────────────────┐ ┌──────────────────┐
│ Servicio X │ │ Servicio Y │
│ ┌────────────┐ │ │ ┌────────────┐ │
│ │ Módulo A │ │ │ │ Módulo C │ │
│ │ Módulo B │ │ │ │ Módulo D │ │
│ └────────────┘ │ │ └────────────┘ │
└──────────────────┘ └──────────────────┘
Para que una arquitectura modular sea efectiva, los límites deben ser reales y verificables. Herramientas como Spring Modulith se integran con IDEs como IntelliJ IDEA para ofrecer una validación visual del encapsulamiento.

Al trabajar en el entorno de desarrollo, podrás identificar rápidamente el estado de tus paquetes mediante íconos: los candados cerrados indican paquetes internos protegidos, mientras que los abiertos representan las APIs públicas. Si el Módulo A intenta acceder a una clase interna del Módulo B, el sistema marcará el error en rojo inmediatamente.
La magia detrás de ModularMS reside en la combinación de límites definidos y el uso estratégico de @Profile y @ComponentScan en Spring Boot.
1. Definición de límites y eventos
Cada módulo gestiona su propia lógica y se comunica mediante eventos para mantener el desacoplamiento. Esto permite que la comunicación sea transparente, ya sea local o distribuida.
@Externalized("new-order.#{#this.productId()}")
public record OrderPlacedEvent(String productId, int quantity) { }
En lugar de configuraciones globales pesadas, utilizamos perfiles para activar solo lo necesario. Al ejecutar con un comando específico de perfiles, el sistema solo carga los módulos requeridos, permitiendo desde un microservicio único hasta un monolito funcional para pruebas locales.
@Configuration
@Profile("orders")
@ComponentScan(basePackages = "me.lbenavides.modularms.order")
public class OrdersModuleConfig { }
Adoptar un despliegue modular es una decisión técnica y también una mejora en la estrategia de entrega de software:
Desde mi perspectiva, la arquitectura debe crecer con el equipo, no por delante de él. Con ModularMS, mi objetivo es demostrar que podemos mantener fronteras limpias y una documentación impecable sin pagar el "impuesto" de la complejidad distribuida desde el primer día.
Al final, se trata de elegir herramientas que nos permitan enfocarnos en lo que realmente importa: entregar valor de forma ágil, sin que la infraestructura se convierta en un obstáculo. Si quieres ver cómo implementar esto en tus propios proyectos, te invito a explorar el repositorio y, por supuesto, ¡cualquier feedback es más que bienvenido!