Tema 2
Elegir entre monolito y microservicios no es una decisión ideológica. Es una decisión de arquitectura. Una mala descomposición puede crear más riesgo, más complejidad y menos control que el sistema original. Por eso hay que entender cuándo conviene dividir, cómo hacerlo y qué señales indican que la partición es segura y sostenible.
Uno de los errores más frecuentes en arquitectura de software es asumir que los microservicios son la evolución natural y obligatoria de cualquier sistema. En la práctica, muchos sistemas funcionan mejor como monolitos bien diseñados que como plataformas distribuidas prematuras.
El problema no es el monolito en sí. El problema es el monolito mal estructurado, difícil de mantener, sin límites claros y con dependencias internas desordenadas. Del mismo modo, el microservicio no es una solución mágica: si se fragmenta un sistema sin criterio, se reemplaza complejidad interna por complejidad distribuida.
Por eso este tema se centra en comparar ambos enfoques y en establecer criterios de descomposición segura. La pregunta no es solo cómo dividir, sino cuándo dividir y qué consecuencias técnicas, operativas y de seguridad trae esa decisión.
Un monolito es una aplicación que se construye, despliega y ejecuta como una sola unidad. Puede tener módulos internos y capas bien separadas, pero desde el punto de vista operativo se trata como un sistema único.
Esto no implica necesariamente mala arquitectura. Un monolito puede ser limpio, modular, mantenible y perfectamente adecuado para muchos contextos. De hecho, para equipos pequeños o productos en etapa inicial suele ser la opción más pragmática.
Un microservicio es una unidad desplegable con responsabilidad bien delimitada, interfaz explícita y autonomía razonable para evolucionar. Se comunica con otros servicios por red y forma parte de un sistema mayor.
En términos prácticos, un microservicio introduce separación técnica y operativa. Esa separación permite mayor independencia, pero también exige más disciplina: versionado de contratos, observabilidad, autenticación entre servicios, políticas de red, manejo de secretos y tolerancia a fallos.
| Aspecto | Monolito | Microservicios |
|---|---|---|
| Despliegue | Una sola unidad | Múltiples unidades independientes |
| Comunicación | Llamadas internas en memoria | Llamadas remotas por red o mensajería |
| Complejidad operativa | Menor al inicio | Mayor desde etapas tempranas |
| Escalado | Generalmente conjunto | Puede ser selectivo por servicio |
| Superficie de ataque | Más concentrada | Más distribuida y extensa |
En muchos casos un monolito es suficiente y conveniente. Si el equipo es pequeño, el dominio aún está cambiando mucho, el producto no tiene necesidades extremas de escalado y la velocidad de coordinación es alta, separar demasiado temprano puede ser un error.
Los microservicios empiezan a justificarse cuando existen necesidades reales que no se resuelven bien dentro de un único despliegue. No se trata solo de que el sistema sea grande, sino de que sus partes tengan ritmos, demandas o responsabilidades suficientemente distintos.
Incluso en estos escenarios, la transición debe ser gradual. Un cambio total y abrupto casi siempre incrementa riesgo técnico y riesgo de seguridad.
Descomponer demasiado pronto puede empeorar el sistema. Lo que antes era una llamada de función pasa a ser una llamada remota; lo que antes era una transacción local pasa a requerir coordinación distribuida; lo que antes era un único punto de autenticación pasa a necesitar múltiples controles de identidad y autorización.
Una descomposición segura no busca generar la mayor cantidad posible de servicios, sino separar capacidades de manera que el sistema conserve claridad, control y resiliencia.
La cohesión indica cuán relacionadas están entre sí las responsabilidades dentro de un componente. El acoplamiento indica cuánto depende ese componente de otros para cumplir su función. Una buena arquitectura busca alta cohesión y bajo acoplamiento.
Si una funcionalidad necesita consultar constantemente múltiples servicios para hacer una tarea simple, probablemente la partición no sea buena. Si un servicio contiene responsabilidades demasiado heterogéneas, probablemente sigue siendo demasiado grande o mal delimitado.
| Señal | Interpretación | Riesgo |
|---|---|---|
| Muchas llamadas para una sola operación | Acoplamiento excesivo entre servicios | Más latencia, más fallos parciales y más exposición |
| Un servicio maneja demasiados procesos distintos | Baja cohesión | Límites difusos y permisos más amplios de lo necesario |
| Cambios coordinados frecuentes entre varios servicios | Dependencias mal separadas | Despliegues riesgosos y menor autonomía real |
Una de las ideas más útiles para descomponer sistemas es la de bounded context: un límite dentro del cual un modelo de negocio tiene sentido consistente. No todos los conceptos significan lo mismo en todas las partes del sistema, y forzar un modelo único suele generar acoplamiento innecesario.
Cuando la descomposición sigue bounded contexts razonables, cada servicio o grupo de servicios puede mantener reglas, datos y vocabulario propios sin contaminar el resto del sistema. Esto mejora claridad y también seguridad, porque ayuda a definir permisos, ownership y flujos de información más explícitos.
Uno de los puntos más delicados al separar un sistema es decidir qué pasa con los datos. Si todos los servicios comparten la misma base de datos y escriben sobre las mismas tablas, la independencia será limitada y la seguridad más difícil de gestionar.
Compartir datos sin reglas claras rompe encapsulamiento, dificulta auditoría y amplía el impacto de una intrusión o de un error operativo.
Una buena partición también ayuda a la seguridad. Si los límites están claros, resulta más fácil definir qué identidades pueden hablar con qué servicios, qué datos necesita cada componente y qué accesos sobran.
No toda fragmentación produce microservicios sanos. Existen anti patrones que suelen aparecer cuando se adopta el estilo por presión organizativa o por seguir modas tecnológicas.
Cuando existe un monolito heredado, lo más prudente suele ser una transición incremental. En lugar de reescribir todo, conviene identificar capacidades con límites razonables, extraerlas de forma gradual y validar que la operación, la observabilidad y la seguridad acompañen esa evolución.
Antes de construir una plataforma de microservicios hay que demostrar que el sistema necesita esa complejidad y que existen límites funcionales suficientemente claros para sostenerla. La arquitectura segura no premia la fragmentación indiscriminada. Premia las decisiones que mejoran control, claridad, resiliencia y capacidad de evolución.
En el próximo tema estudiaremos dominios, bounded contexts y diseño orientado a capacidades para profundizar cómo se identifican límites arquitectónicos sólidos.