Email copiado — support@tuurt.com
Cargando experiencia
arquitectura · 07 de mayo de 2026 · 9 min

Monolito modular: el camino intermedio antes de microservicios

No todos los proyectos necesitan microservicios desde el día uno. El monolito modular resuelve los problemas reales del monolito tradicional sin la complejidad operacional de los microservicios — y te deja la puerta abierta para migrar después.

Por Equipo Tuurt

Monolito modular: el camino intermedio antes de microservicios

Microservicios se convirtió en sinónimo de "arquitectura seria". Si no tenés microservicios, parece que no estás haciendo las cosas bien. El resultado: equipos que arrancan con microservicios desde el día uno en proyectos que todavía no tienen product-market fit, y pagan un costo operacional brutal por una flexibilidad que no necesitan todavía.

Hay un camino intermedio que resuelve los problemas reales del monolito tradicional sin la complejidad operacional de los microservicios: el monolito modular.


Qué es un monolito modular

Un monolito modular es una sola aplicación desplegable que internamente está organizada con límites fuertes entre dominios. Cada módulo tiene su propio dominio, sus propias reglas de negocio y —en la versión más estricta— su propia persistencia. Los módulos se comunican entre sí a través de interfaces o eventos internos, nunca accediendo directamente a los internals del otro.

La diferencia con un monolito tradicional es el nivel de disciplina en los límites internos. En un monolito tradicional, cualquier parte del código puede llamar a cualquier otra. En un monolito modular, los módulos son ciudadanos de primera clase con APIs internas definidas.

La diferencia con microservicios es que todo corre en el mismo proceso. No hay red entre módulos, no hay serialización, no hay service discovery, no hay gestión de fallos distribuidos.


Los problemas que resuelve

El monolito tradicional se pudre con el tiempo

El problema del monolito tradicional no es que sea un monolito. Es que sin disciplina de diseño, los límites entre dominios se erosionan. Seis meses después del lanzamiento, el módulo de Pagos llama directamente a la base de datos de Usuarios, el módulo de Notificaciones conoce los detalles de implementación de Pedidos, y cambiar cualquier cosa requiere entender todo el sistema.

El monolito modular previene esto por diseño. Los límites son explícitos y se verifican en code review o, si usás herramientas como ArchUnit o dependency-cruiser, en el pipeline de CI.

Los microservicios prematuros cuestan demasiado

Microservicios resuelve problemas reales: equipos grandes que necesitan deployar de forma independiente, dominios con requisitos de escala muy distintos, necesidad de usar distintas tecnologías por servicio.

Pero también introduce complejidad real: necesitás orquestación (Kubernetes o equivalente), observabilidad distribuida (tracing, logging centralizado), manejo de consistencia eventual, contratos entre servicios, gestión de fallos de red. Todo eso tiene un costo de ingeniería permanente.

Si tu equipo tiene 3 personas y tu producto está en fase de validación, ese costo probablemente no se justifica todavía.


Cómo se estructura

Cada módulo tiene su propio directorio y expone solo lo que otros módulos necesitan conocer:

src/
  users/
    api/
      users.service.ts
    internal/
      users.repository.ts
      users.entity.ts
    users.module.ts
  orders/
    api/
      orders.service.ts
    internal/
      orders.repository.ts
  payments/

La regla: nada fuera de api/ es accesible desde otros módulos. Si OrdersService necesita datos del usuario, llama a la interfaz pública de UsersService, no al repositorio.

Persistencia por módulo

La versión más estricta le da a cada módulo su propio schema de base de datos. En PostgreSQL:

CREATE SCHEMA users;
CREATE SCHEMA orders;
CREATE SCHEMA payments;

Los módulos no hacen JOINs cruzados entre schemas. Si Orders necesita el nombre del usuario, lo obtiene llamando al módulo Users en tiempo de ejecución. Costo: algunas queries requieren dos llamadas en vez de un JOIN. Beneficio: cuando llegue el momento de extraer Orders como microservicio, su schema ya está aislado.

Comunicación entre módulos

Llamadas síncronas por interfaz: OrdersService llama directamente a UsersService.findById(). Simple, trazable, tipado completo. Funciona para la mayoría de los casos.

Eventos internos: Orders emite un evento OrderCompleted y Payments escucha. Desacopla emisor y receptor. Bueno para flujos donde el emisor no necesita la respuesta inmediata.


Cuándo es mejor que microservicios desde el día uno

Equipo pequeño (menos de 10 ingenieros): el overhead operacional de microservicios consume una fracción significativa de la capacidad del equipo.

Producto en etapa de validación: los límites de dominio correctos no son obvios al principio. Mover lógica entre módulos es barato. Cambiar límites entre microservicios implica cambios de contrato, migraciones de datos y coordinación entre equipos.

Dominio con requisitos de escala uniformes: si todos los dominios tienen necesidades similares, escalar el monolito completo es más simple que escalar servicios individuales.

Sin necesidad de tecnologías distintas por dominio: si no necesitás Python para ML en un servicio y Go para otro, el argumento de heterogeneidad tecnológica no aplica.


La puerta abierta a microservicios

Cuando llegue el momento de extraer un dominio como microservicio:

  1. El módulo ya tiene su API interna definida → esa API se convierte en la API del servicio.
  2. El schema ya está aislado → la migración de datos es directa.
  3. Las llamadas internas al módulo → se convierten en llamadas HTTP o mensajes en un bus.

En un monolito tradicional sin límites, la misma extracción requiere primero entender y separar las dependencias mezcladas. Es el doble de trabajo.


El riesgo real: mantener los límites

El monolito modular no se mantiene solo. El riesgo principal es la erosión gradual de los límites: alguien accede directamente al repositorio de otro módulo "porque era más rápido", y seis meses después los límites son nominales.

Mitigaciones:

  • Revisión de arquitectura en code review: cualquier importación que cruce el límite de un módulo es un flag.
  • Herramientas de análisis de dependencias: dependency-cruiser (Node.js), ArchUnit (Java), NDepend (.NET) pueden fallar el build si se violan las reglas.
  • Documentación explícita de qué es público y qué es interno en cada módulo.

Sin disciplina de equipo, el monolito modular se convierte en monolito tradicional en 6 meses. Con disciplina, sigue siendo una arquitectura sana por años.


Conclusión

El monolito modular no es la arquitectura de los que no pudieron hacer microservicios. Es la arquitectura correcta para una etapa específica: cuando el dominio todavía está evolucionando, el equipo es pequeño y el costo operacional de los microservicios no se justifica.

Bien hecho, te da límites claros hoy y una migración a microservicios ordenada mañana. Mal hecho, es un monolito tradicional con carpetas mejor nombradas.

La diferencia está en mantener los límites.

arquitectura microservicios monolito backend buenas-practicas diseño
← Volver al blog