Volver al blog
Arquitectura

Microservicios vs. monolito: cuándo vale la pena la complejidad

La arquitectura de microservicios se ha convertido en el estándar aspiracional de cualquier equipo técnico ambicioso. Pero adoptarla sin criterio es uno de los errores más caros que puede cometer una empresa de software.

Equipo Polaris10 de abril de 202611 min de lectura

El mito del monolito obsoleto

Hay una narrativa muy extendida en el sector que equipara el monolito con deuda técnica acumulada, equipos desorganizados y código de los años noventa que nadie se atreve a tocar. Y hay una narrativa paralela que equipara los microservicios con modernidad, escalabilidad y buenas prácticas de ingeniería.

Las dos narrativas son falsas.

El monolito es simplemente una arquitectura. Como cualquier arquitectura, tiene ventajas e inconvenientes que se evalúan en contexto. Y el contexto más relevante no es el tamaño del equipo ni el número de usuarios actuales: es la madurez del dominio, la velocidad de cambio esperada y la capacidad operativa del equipo que va a mantenerlo.

Hemos construido sistemas en ambas arquitecturas, y la decisión nunca ha sido obvia. Este artículo es el destilado de esa experiencia.


Qué es realmente un microservicio

Antes de comparar, conviene aclarar qué es un microservicio. No es simplemente un servicio pequeño. Un microservicio es un componente desplegable de forma independiente, con su propio proceso, su propio almacenamiento de datos y una interfaz bien definida hacia el exterior.

La parte de despliegue independiente es la más importante. Si para desplegar el servicio A tienes que coordinar el despliegue del servicio B, no tienes microservicios: tienes un sistema distribuido acoplado, que es lo peor de los dos mundos.

La parte del almacenamiento propio también es más radical de lo que parece. No se trata solo de separar tablas en el mismo base de datos: se trata de que cada servicio sea dueño completo de sus datos y que otros servicios solo accedan a ellos a través de la API, nunca directamente.

Cuando estos principios se aplican de verdad, la complejidad operativa que se introduce es enorme. Y eso tiene que estar justificado.


Dónde gana el monolito

Velocidad de iteración en producto joven

Un producto que aún no ha encontrado su encaje en el mercado necesita iterar rápido. Cambiar una feature en un monolito es una operación de horas: editas el código, haces el build, lo despliegas. Cambiar una feature que cruza tres microservicios implica coordinar cambios en múltiples repositorios, versionar APIs, gestionar retrocompatibilidad y desplegar en el orden correcto.

La startup que construye su primer producto sobre microservicios está pagando un coste operativo de empresa madura para construir algo que quizás va a tirar en seis meses.

Transacciones de datos complejas

Cuando una operación de negocio necesita modificar múltiples entidades de forma atómica —o todo o nada—, los microservicios crean un problema serio. Las transacciones ACID no cruzan bases de datos. Tienes que implementar patrones como Saga, con su complejidad y sus garantías más débiles, o aceptar consistencia eventual donde antes tenías consistencia fuerte.

En sistemas financieros, clínicos o de inventario, la consistencia no es negociable. El monolito la da gratis.

Equipos pequeños

Los microservicios necesitan madurez organizativa. El modelo de Conway —que dice que el software tiende a replicar la estructura de comunicación del equipo que lo construye— funciona en los dos sentidos. Un equipo de cinco personas que gestiona quince servicios gasta la mayor parte de su tiempo en infraestructura, no en producto.

La regla práctica que usamos: un microservicio necesita al menos un equipo dedicado que lo entienda en profundidad. Si no puedes asignar un equipo a cada servicio, el número de servicios es excesivo.


Dónde ganan los microservicios

Escala diferencial

Cuando partes muy específicas del sistema necesitan escalar de forma independiente, los microservicios son difícilmente sustituibles. Un monolito escala como unidad: si el módulo de procesamiento de pagos necesita diez veces más capacidad, tienes que escalar el sistema entero.

Con microservicios, escala solo el servicio de pagos. A los precios actuales del cloud, la diferencia económica en sistemas de alto volumen es muy significativa.

Equipos grandes con dominios separados

La promesa real de los microservicios no es técnica: es organizativa. Permite que equipos distintos trabajen sobre partes distintas del sistema sin coordinación constante. Un equipo puede desplegar su servicio diez veces al día sin afectar al resto.

Esto solo funciona cuando los dominios están bien delimitados y los equipos son suficientemente autónomos. Si los servicios están muy acoplados —si cada cambio requiere coordinar con otros equipos—, los microservicios añaden fricción sin dar libertad.

Tecnología heterogénea

Cuando distintas partes del sistema tienen requisitos de tecnología incompatibles —un componente de ML que necesita Python, un servicio de tiempo real que necesita Go, un backend de negocio en TypeScript— los microservicios permiten la combinación sin compromisos.


El patrón que recomendamos: monolito modular primero

Para la mayoría de proyectos en fase de crecimiento, la mejor arquitectura no es ni el monolito desorganizado ni los microservicios prematuros: es el monolito modular.

Un monolito modular es un único servicio desplegable donde el código está organizado en módulos con fronteras claras: cada módulo tiene su propia carpeta, sus propias interfaces internas y sus propias reglas de acceso a datos. Los módulos no se llaman directamente entre sí excepto a través de interfaces bien definidas.

La ventaja es que obtienes la velocidad de iteración del monolito y la organización del código que facilita la futura extracción de servicios. Cuando un módulo crece hasta el punto en que justifica ser un servicio independiente —por necesidades de escala, por tamaño del equipo o por requisitos de tecnología—, la frontera ya está trazada. La extracción es mucho más barata que si el código estaba mezclado.

Esta es la arquitectura con la que empezamos Nexen, nuestra plataforma de comunicaciones. Durante los primeros meses de product-market fit, la velocidad de iteración era prioritaria. Cuando el volumen de llamadas VoIP justificó escala diferencial, el servicio de telefonía ya tenía una frontera clara y la extracción fue quirúrgica.


Las señales que indican que es momento de separar

No hay un umbral universal. Pero hay señales que indican que la extracción de un servicio empieza a tener sentido:

  • El módulo tiene un ciclo de despliegue propio: se despliega con más frecuencia que el resto del sistema, o necesita coordinación especial.
  • Tiene requisitos de escala distintos: necesita más recursos que el resto y la diferencia es sostenida, no puntual.
  • Lo mantiene un equipo dedicado que no trabaja en otras partes del sistema.
  • Sus requisitos de tecnología son incompatibles con el resto del sistema.
  • Tiene una frontera de dominio limpia: los cambios dentro del módulo raramente requieren cambios fuera.

Si ninguna de estas señales está presente, la extracción añade coste operativo sin contrapartida.


Los errores más caros que hemos visto

Extraer por analogía, no por necesidad

El error más frecuente: el equipo lee que Netflix tiene cientos de microservicios y decide que ellos también deberían tenerlos. Netflix tiene miles de ingenieros, años de acumulación de deuda técnica en sistemas heredados y problemas de escala que justifican cada decisión de su arquitectura. Tomar sus conclusiones sin tener sus problemas es diseñar la solución para la empresa que no eres.

Servicios que comparten base de datos

Si separas el código en servicios pero los conectas todos a la misma base de datos, tienes lo peor de los dos mundos: la complejidad de los servicios distribuidos sin el aislamiento que los justifica. Cualquier cambio de esquema puede romper múltiples servicios. No hay independencia real.

La trampa del acoplamiento temporal

Servicios que necesitan estar disponibles al mismo tiempo para funcionar —que se llaman de forma síncrona en cadena— tienen un acoplamiento de disponibilidad que multiplica los puntos de fallo. Si el servicio A llama al B que llama al C, la disponibilidad del sistema completo es el producto de la disponibilidad individual de cada uno: si cada uno tiene 99.9%, el sistema tiene 99.7%.

La solución es comunicación asíncrona mediante eventos y colas de mensajes, pero introduce su propia complejidad de consistencia eventual.


Una decisión de negocio, no solo técnica

La elección de arquitectura tiene implicaciones que van más allá del código. Afecta a cuántas personas necesitas para operar el sistema, qué perfiles técnicos buscas, cómo organizas los equipos y cuánto tiempo tarda en llegar una feature a producción.

Nuestra recomendación: empieza con la arquitectura más simple que resuelva el problema actual, con fronteras de módulo claras que permitan extraer servicios cuando la necesidad sea real. No diseñes para los problemas que crees que vas a tener en tres años. Diseña para los problemas que tienes hoy, con la capacidad de cambiar cuando los problemas cambien.

Arquitectura de sistemas y código
Arquitectura de sistemas y código
La arquitectura correcta es la que permite a tu equipo actual moverse rápido y cambiar cuando sea necesario.

La complejidad que no gestionas hoy es deuda técnica que no acumulas. Eso siempre tiene valor.

Etiquetas

#arquitectura#microservicios#monolito#backend#escalabilidad
¿Quieres llevarlo a tu empresa?

Cuéntanos tu proyecto

Te ayudamos a encontrar la solución tecnológica adecuada, sin humo ni presiones.

Hablar con nuestro equipo