Arquitectura de software

Monolito modular vs microservicios: cómo decidir

Los microservicios se presentan como el paso natural tras el monolito, pero muchas aplicaciones no tienen el problema que justifica ese salto. Cómo decidir.

Por Leyton Manuel Espitia Diaz 5 min de lectura

Fragmento de código C# que compara una llamada en proceso con una llamada HTTP con reintentos

Los microservicios suelen presentarse como el siguiente paso después de un monolito: la aplicación creció, se volvió difícil de mantener, así que hay que dividirla. En la práctica, muchas aplicaciones no tienen un problema de arquitectura que justifique ese salto. Tienen un problema de organización interna del código, y los microservicios no lo resuelven: lo distribuyen por la red.

Qué problema resuelven los microservicios

Los microservicios resuelven, sobre todo, un problema organizacional: permiten que equipos distintos desarrollen, desplieguen y escalen partes del sistema de forma independiente.

  • El equipo de pagos despliega cinco veces al día sin coordinar con el de catálogo.
  • El servicio de búsqueda escala a 20 instancias mientras el de facturación sigue con dos.
  • Una falla en recomendaciones no tumba el proceso de compra.

Si tu sistema no tiene varios equipos que se estorban al desplegar, ni partes con necesidades de escala muy distintas, los microservicios resuelven un problema que no tienes.

Lo que cuestan

Cada llamada se vuelve una llamada de red

// En un monolito modular: una llamada en memoria
var product = await catalog.GetProductAsync(productId, ct);

// En microservicios: red, serialización, latencia y fallos posibles
var response = await catalogClient.GetAsync($"/api/products/{productId}", ct);
if (!response.IsSuccessStatusCode) { /* ¿reintentar? ¿fallar? ¿usar caché? */ }
var product = await response.Content.ReadFromJsonAsync<ProductDto>(ct);

Cada llamada que antes no podía fallar ahora puede tardar, fallar a medias o fallar del todo. Hacen falta tiempos límite, reintentos, circuit breakers y una decisión para cada caso de error.

Adiós a las transacciones

Crear un pedido y reservar el inventario en una sola transacción es trivial en un monolito. Entre dos servicios con bases de datos separadas, no existe esa transacción. Hay que diseñar con consistencia eventual, sagas y compensaciones: "si el pago falla, libera la reserva de inventario".

Operación multiplicada

Diez servicios son diez pipelines de despliegue, diez configuraciones, diez conjuntos de logs y métricas, y la necesidad de tracing distribuido para entender una sola petición. Sin una plataforma y un equipo que la mantenga, esa operación consume el tiempo que antes se dedicaba a funcionalidades.

Depuración distribuida

Un error que en un monolito se ve en una pila de llamadas, en microservicios se reconstruye uniendo trazas de cinco servicios.

El monolito modular: el punto medio

Un monolito modular mantiene un solo despliegue, pero con módulos que tienen límites estrictos: contratos públicos, internos protegidos, datos propios y comunicación por eventos donde tiene sentido. Lo explicamos en detalle en arquitectura modular en aplicaciones .NET.

Con eso se obtiene buena parte de lo que se busca con los microservicios:

Beneficio Monolito modular Microservicios
Límites claros entre áreas Sí Sí
Datos propios por área Sí (esquemas) Sí (bases separadas)
Equipos trabajando en paralelo Sí, con un despliegue compartido Sí, con despliegues independientes
Escalar áreas por separado No Sí
Transacciones locales Sí No
Llamadas entre áreas En memoria Por red
Costo de operación Bajo Alto

Los síntomas que sí justifican separar un servicio

No se migra todo de una vez. Se extrae un módulo cuando aparece una razón concreta:

  • Escala muy distinta: un módulo necesita 20 veces más capacidad que el resto, y escalar toda la aplicación por él es caro.
  • Ritmo de despliegue incompatible: un equipo necesita desplegar varias veces al día y el resto del sistema no puede seguir ese ritmo.
  • Aislamiento de fallos: una parte inestable o con dependencias riesgosas no debe poder tumbar el proceso crítico.
  • Tecnología distinta: una parte necesita un lenguaje o un runtime diferente (por ejemplo, procesamiento de datos o modelos de machine learning).
  • Requisitos de seguridad o cumplimiento que exigen aislar ciertos datos.

Si el monolito ya es modular, extraer un módulo es reemplazar las llamadas en memoria a su contrato por llamadas de red, y mover su esquema a otra base de datos. Sigue siendo trabajo, pero acotado. Si el monolito no tiene límites, extraer un servicio es primero descubrir dónde están, y eso es lo más costoso.

Errores frecuentes al ir a microservicios

  • Dividir por capas técnicas (un servicio de "datos", otro de "lógica"): todas las funcionalidades atraviesan todos los servicios.
  • Compartir la base de datos entre servicios: se paga el costo de la red sin obtener la independencia.
  • Servicios demasiado pequeños: cada operación de negocio requiere orquestar cinco llamadas.
  • Hacerlo antes de entender el dominio: los límites equivocados son mucho más caros de corregir entre servicios que entre módulos.

El trade-off

Los microservicios cambian complejidad del código por complejidad operacional y distribuida. Para organizaciones con muchos equipos y necesidades de escala diversas, ese cambio vale la pena. Para un equipo de cinco personas con un producto que todavía está encontrando su forma, casi nunca.

Cuándo elegir monolito modular

  • Uno o pocos equipos.
  • Dominio que todavía está cambiando.
  • Necesidades de escala similares en todo el sistema.
  • Sin una plataforma madura para operar muchos servicios.

Cuándo elegir microservicios

  • Varios equipos autónomos que se bloquean al desplegar.
  • Partes del sistema con necesidades de escala o disponibilidad muy distintas.
  • Límites del dominio claros y estables.
  • Capacidad real para operar sistemas distribuidos.

Conclusión

La mayoría de sistemas que se benefician de los microservicios habrían llegado ahí mejor desde un monolito modular. Empieza con límites claros dentro de un solo despliegue y extrae servicios cuando un síntoma concreto lo justifique. No necesitas microservicios porque tu aplicación creció: los necesitas cuando tu organización y tus requisitos de escala ya no caben en un solo despliegue.

Leyton Manuel Espitia Diaz

Escrito por

Leyton Manuel Espitia Diaz

CEO y fundador de Nakanaba

Desarrollador de software y fundador de Nakanaba. Lidera la arquitectura de Vitrin: backend en .NET, aplicaciones en Angular y .NET MAUI, SQL Server y servicios en Cloudflare.

¿Tu sistema necesita una revisión de arquitectura?

Te ayudamos a decidir qué estructura necesita tu software hoy y cómo prepararlo para crecer, sin sobreingeniería.

Ver desarrollo a medida