Arquitectura de Software

Monolito a microservicios: cómo elegir el primer módulo que conviene separar

Analiza cómo elegir el primer módulo que conviene extraer de un monolito, comparando límites de dominio, acoplamiento, criticidad operativa y costos con la opción de mejorar un monolito modular.

Monolito a microservicios: cómo elegir el primer módulo que conviene separar

Una aplicación de pedidos puede comenzar como un monolito sencillo: un único despliegue contiene el catálogo de productos, la gestión de inventario y la facturación. Con el tiempo, cada área puede adquirir reglas propias, ciclos de cambio diferentes y necesidades operativas específicas. El equipo entonces considera separar algunos módulos en microservicios.

El problema es que el módulo más visible no siempre es el mejor candidato para extraer. Separar una parte del sistema modifica las fronteras de datos, introduce comunicación remota, requiere observabilidad adicional y puede aumentar el costo operativo. En este artículo veremos cómo evaluar esa decisión, cuándo conviene extraer un servicio, cuándo es preferible modularizar el monolito y cómo avanzar de forma incremental.

La primera decisión no es tecnológica: es arquitectónica

Pasar de un monolito a microservicios no debería comenzar con la elección de una plataforma, un broker de mensajes o un clúster de Kubernetes. La pregunta inicial es otra:

¿Qué problema concreto del sistema actual resolvería la separación?

Algunas motivaciones pueden ser razonables:

  • Un módulo necesita desplegarse con una frecuencia muy diferente al resto.
  • Una parte del sistema requiere escalar de forma independiente.
  • Existe un límite de dominio claro y sus reglas cambian con autonomía.
  • Un equipo necesita operar una capacidad sin depender continuamente de otro equipo.
  • Los requisitos de seguridad, disponibilidad o cumplimiento son distintos.

En cambio, razones como “los microservicios son más modernos”, “el monolito ya es grande” o “queremos usar Kubernetes” no describen por sí mismas un problema que la extracción vaya a resolver.

Un monolito puede ser difícil de mantener por distintas causas: dependencias ocultas, responsabilidades mezcladas, acceso directo a tablas ajenas o falta de pruebas. Ninguna de esas dificultades desaparece automáticamente al crear un nuevo proceso. Si el diseño interno no tiene límites claros, es posible terminar con un monolito distribuido: varios servicios que deben cambiarse y desplegarse juntos, con dependencias remotas más difíciles de diagnosticar.

El ejemplo: pedidos, catálogo, inventario y facturación

Consideremos una aplicación de pedidos con cuatro capacidades principales:

  • Catálogo: productos, precios visibles, descripciones y disponibilidad comercial.
  • Inventario: existencias, reservas y movimientos de stock.
  • Pedidos: creación, actualización y seguimiento del ciclo de vida de una orden.
  • Facturación: emisión de comprobantes, aplicación de reglas fiscales y comunicación con un proveedor externo.

En una primera versión, todas estas capacidades pueden compartir una base de datos y ejecutarse dentro de la misma aplicación. El flujo de compra podría ser similar a este:

  1. El cliente consulta el catálogo.
  2. Agrega productos al pedido.
  3. El sistema verifica o reserva inventario.
  4. Se confirma el pedido.
  5. Se solicita la facturación.

A simple vista, cada área parece un candidato natural para convertirse en un servicio. Sin embargo, la separación no depende solo de que exista un nombre diferente para cada módulo. Hay que analizar sus responsabilidades, sus datos y las dependencias que participan en cada operación.

Preguntas para descubrir límites de dominio
  • ¿Qué reglas de negocio pertenecen exclusivamente a la capacidad?
  • ¿Qué datos puede modificar el módulo y cuáles solo debería consultar?
  • ¿Qué eventos o resultados publica hacia otras capacidades?
  • ¿Qué cambios suelen ocurrir juntos?
  • ¿Qué operaciones deben ser estrictamente consistentes?
  • ¿Qué equipo conoce y mantiene esas reglas?

Si una operación necesita actualizar varias tablas de distintos módulos dentro de una misma transacción, todavía puede existir un acoplamiento de dominio importante. No significa que la separación sea imposible, pero sí que requiere resolver primero cómo se coordinarán esas reglas.

Qué evaluar antes de elegir el primer módulo

El primer candidato debe evaluarse desde varias dimensiones. Una extracción atractiva en una dimensión puede ser mala en otra.

1. Claridad del límite de dominio

Un buen candidato tiene responsabilidades coherentes y reglas relativamente autónomas. En el ejemplo, la facturación puede tener políticas propias relacionadas con numeración, impuestos, comprobantes y reintentos frente a un proveedor externo.

Pero si facturación necesita leer y modificar directamente datos internos de pedidos, clientes, inventario y catálogo, el límite puede no estar suficientemente definido. Extraerla sin corregir ese diseño trasladaría el acoplamiento desde llamadas internas hacia APIs o eventos.

2. Frecuencia y naturaleza de los cambios

Un módulo que cambia constantemente mientras el resto permanece estable puede beneficiarse de un ciclo de despliegue independiente. También puede ocurrir lo contrario: si todos los cambios de una funcionalidad requieren modificar pedidos, inventario y facturación al mismo tiempo, separarla puede generar coordinación adicional sin aportar autonomía real.

No conviene medir únicamente cuántas líneas de código cambian. Hay que observar qué reglas cambian juntas y qué dependencias deben validarse en cada entrega.

3. Acoplamiento de datos

El acceso compartido a la base de datos es uno de los obstáculos más frecuentes. Un servicio no tiene una frontera real si otros módulos pueden escribir directamente en sus tablas.

Antes de extraer un componente, conviene identificar:

  • Tablas que solo utiliza el módulo candidato.
  • Tablas leídas por múltiples módulos.
  • Escrituras cruzadas que forman parte de una misma operación.
  • Consultas que dependen de joins entre dominios.
  • Procesos batch, reportes o integraciones que acceden directamente a los datos.

Una estrategia gradual puede comenzar restringiendo el acceso a través de interfaces internas, aunque el almacenamiento siga siendo compartido durante una etapa. Es un paso de modularización, no todavía una independencia completa, pero ayuda a hacer explícitos los contratos.

4. Criticidad operativa

Separar un módulo que participa en una operación crítica puede aumentar el riesgo. Por ejemplo, inventario suele estar involucrado en decisiones de disponibilidad y reserva. Un fallo de comunicación, un reintento mal diseñado o una respuesta atrasada puede producir reservas duplicadas o inconsistencias.

La criticidad no significa que inventario nunca deba separarse. Significa que la extracción debe incluir decisiones explícitas sobre idempotencia, concurrencia, consistencia, recuperación ante fallos y observabilidad.

5. Costo de operar de forma distribuida

Un servicio separado necesita más que un repositorio independiente. Puede requerir:

  • Pipeline de construcción y despliegue.
  • Gestión de configuración y secretos.
  • Logs, métricas y trazas correlacionadas.
  • Alertas y procedimientos de respuesta.
  • Pruebas de contrato e integración.
  • Políticas de seguridad y control de acceso.
  • Estrategias de versionado y compatibilidad.

Si la organización todavía no puede diagnosticar con claridad un fallo dentro del monolito, agregar saltos de red puede empeorar el tiempo de resolución. La arquitectura distribuida exige capacidades operativas proporcionales a su complejidad.

Comparación de candidatos en la aplicación de pedidos

Supongamos que el equipo analiza tres alternativas: catálogo, inventario y facturación.

Catálogo

El catálogo podría parecer un buen primer candidato porque recibe muchas consultas y tiene reglas diferentes a las de un pedido. También podría requerir un modelo de lectura optimizado o mecanismos de caché.

Sin embargo, si sus datos se consultan mediante joins directos desde pedidos, reportes y administración, la extracción no será sencilla. Además, escalar las consultas del catálogo no necesariamente exige separar todo el módulo: una API interna bien definida, índices adecuados, caché o réplicas de lectura podrían resolver parte del problema manteniendo el monolito.

Inventario

Inventario suele tener un límite de dominio reconocible, pero participa directamente en el flujo de compra. Las reservas, liberaciones y confirmaciones deben manejar concurrencia y estados intermedios.

Puede ser un candidato válido si existe una necesidad concreta de independencia operativa o de escalado. No obstante, su extracción requiere diseñar cuidadosamente qué significa “reservar”, qué sucede cuando un pedido se cancela y cómo se recupera el sistema ante una respuesta perdida.

Facturación

Facturación puede ofrecer una frontera interesante cuando integra proveedores externos, tiene reglas fiscales propias o debe procesar operaciones de forma asíncrona. Una solicitud de factura puede pasar por estados como pendiente, emitida, rechazada o reintentando.

Este módulo puede ser un buen candidato si se define una interfaz basada en una intención de negocio, por ejemplo “solicitar facturación”, en lugar de exponer tablas o permitir que otros componentes modifiquen directamente su estado interno.

El riesgo principal está en asumir que la facturación siempre debe completarse dentro de la misma transacción que crea el pedido. En muchos escenarios, el pedido puede quedar confirmado con un estado de facturación pendiente, siempre que el negocio acepte ese comportamiento y existan mecanismos claros para reintentos y conciliación.

Matriz de decisión para seleccionar el primer servicio

Una matriz no reemplaza el criterio arquitectónico, pero ayuda a hacer visibles las suposiciones. El equipo puede puntuar cada candidato con una escala definida internamente, por ejemplo de bajo a alto, y justificar cada valoración.

Criterio Catálogo Inventario Facturación
Claridad del límite de dominio Media Media/alta Alta
Acoplamiento con datos externos Alto Medio Medio
Necesidad de ciclo de despliegue propio Por validar Por validar Posiblemente alta
Criticidad de consistencia Media Alta Alta, con posibles flujos asíncronos
Complejidad operativa adicional Media Alta Media/alta

La tabla no indica que facturación deba separarse siempre. Sugiere una hipótesis para investigar. Un análisis más completo puede añadir criterios como:

  • Autonomía del equipo responsable.
  • Volumen y patrón de tráfico.
  • Necesidades diferentes de disponibilidad.
  • Requisitos de seguridad o cumplimiento.
  • Madurez de las pruebas automatizadas.
  • Facilidad para definir contratos estables.
  • Impacto de una falla del módulo.
  • Esfuerzo de migración y reversibilidad.

También es útil registrar el nivel de certeza de cada valoración. Una puntuación basada en percepciones no debería presentarse como una conclusión definitiva. El equipo puede comenzar con un mapa de dependencias, revisar consultas y observar despliegues reales antes de decidir.

Cuándo conviene mejorar el monolito modular en lugar de extraer

La modernización no tiene por qué terminar en microservicios. En muchos casos, el siguiente paso más seguro es convertir un monolito difícil de modificar en un monolito modular.

Esta opción puede ser adecuada cuando:

  • El sistema todavía tiene un equipo pequeño o mediano.
  • Las capacidades comparten muchas transacciones y datos.
  • No existe una necesidad clara de escalar o desplegar de forma independiente.
  • La plataforma operativa aún no soporta bien sistemas distribuidos.
  • El principal problema es el acoplamiento del código, no el proceso de despliegue.
  • El producto todavía está validando reglas de negocio y sus límites cambian con frecuencia.

Un monolito modular puede aplicar reglas como:

  • Cada módulo tiene una API interna explícita.
  • Los módulos no acceden directamente a las tablas de otros módulos.
  • Las dependencias entre módulos se revisan y se mantienen unidireccionales cuando sea posible.
  • Los casos de uso están separados de los detalles de persistencia.
  • Los eventos internos representan cambios de negocio relevantes.
  • Las pruebas verifican los contratos entre módulos.

Esta estructura reduce el riesgo de una futura extracción, pero también puede ser el estado final adecuado. No todos los sistemas necesitan convertirse en una colección de servicios independientes.

Plan de migración incremental y reversible

Cuando exista una razón concreta para separar un módulo, la migración debería dividirse en pasos pequeños. El objetivo es evitar un cambio irreversible que mezcle rediseño funcional, migración de datos y nueva plataforma en una sola entrega.

1. Definir el problema y el resultado esperado

Documenta qué limitación se intenta resolver: frecuencia de despliegue, aislamiento operativo, integración externa, escalado o propiedad de un equipo. También define cómo se verificará el resultado sin depender de métricas inventadas o de expectativas ambiguas.

2. Mapear dependencias y flujos críticos

Identifica llamadas, tablas, procesos batch, integraciones, tareas programadas y reportes que dependen del módulo. Incluye los caminos de error: timeouts, reintentos, duplicados, caídas del proveedor y mensajes procesados más de una vez.

3. Estabilizar el contrato

Expón una interfaz que represente capacidades del dominio, no estructuras internas de la base de datos. El contrato puede ser síncrono o asíncrono según las necesidades del negocio, pero debe definir estados, errores, idempotencia y compatibilidad.

4. Reducir el acceso compartido a datos

Antes o durante la extracción, elimina escrituras directas desde otros módulos. Si es necesario mantener temporalmente una base compartida, establece una frontera de acceso y registra las excepciones que todavía deben eliminarse.

5. Extraer una ruta de negocio acotada

En lugar de migrar todo el módulo, selecciona un flujo concreto. Por ejemplo, facturación de un tipo de pedido o una operación específica de consulta. Mantén una estrategia de coexistencia que permita comparar resultados y volver atrás si el comportamiento no es correcto.

6. Incorporar operación y observabilidad

El nuevo servicio debe poder diagnosticarse de forma independiente. La correlación de solicitudes, los logs estructurados, las métricas de errores y latencia, y las trazas distribuidas son parte de la arquitectura, no tareas posteriores.

7. Migrar datos y retirar dependencias gradualmente

La propiedad de los datos debe transferirse de forma explícita. Evita que el servicio nuevo sea solo una capa delante de las mismas tablas que siguen siendo modificadas desde el monolito. Cuando el flujo esté estabilizado, elimina el camino antiguo y documenta la nueva responsabilidad.

Errores frecuentes al separar el primer módulo

  • Elegir por tamaño: el módulo con más código no necesariamente tiene el mejor límite de dominio.
  • Crear servicios por entidad: separar “productos”, “clientes” o “facturas” solo por el nombre puede fragmentar reglas que deben permanecer juntas.
  • Mantener una base compartida sin control: si todos siguen escribiendo en las tablas del servicio, la autonomía es principalmente nominal.
  • Ignorar los fallos de red: una llamada remota puede fallar, tardar, duplicarse o devolver una respuesta perdida.
  • Usar eventos sin definir semántica: publicar mensajes no resuelve por sí mismo la consistencia ni la coordinación.
  • Extraer sin pruebas suficientes: las pruebas de integración y de contrato son importantes cuando parte del comportamiento deja de ejecutarse dentro del mismo proceso.
  • Confundir independencia de despliegue con independencia de dominio: poder desplegar un componente por separado no significa que sus reglas y datos estén desacoplados.

Conclusión: el primer servicio debe resolver un problema real

Elegir el primer módulo para separar exige evaluar límites de dominio, cambios, datos, criticidad y capacidad operativa. En una aplicación de pedidos, catálogo, inventario y facturación pueden parecer candidatos evidentes, pero cada uno introduce riesgos diferentes.

Facturación podría ser una buena hipótesis cuando tiene reglas e integraciones propias. Inventario puede justificar una separación si existen necesidades claras de autonomía, aunque requiere especial cuidado con la consistencia. Catálogo quizá necesite optimización o modularización antes que un proceso independiente. La respuesta correcta depende del problema que el sistema realmente presenta.

Si el principal inconveniente es el acoplamiento interno, un monolito modular puede ofrecer una mejora significativa con menos complejidad operativa. Si se decide extraer, conviene hacerlo mediante una migración incremental, con contratos explícitos, observabilidad, pruebas y una ruta de retorno.

Antes de extraer un servicio, evalúa qué problema operativo resolverá y qué nuevas dependencias introducirá. Ese análisis puede ser el paso más importante de toda la modernización. Mentores Tech puede ayudarte a profundizar en decisiones de arquitectura moderna mediante formación, mentoría y asesoría técnica orientada a contextos reales de ingeniería.

Siguiente paso

Profundiza en patrones de arquitectura

Este artículo explica el concepto. El ebook junta los patrones, cuándo usar cada uno y cómo compararlos. Cuesta USD 15.

Crear cuenta

Recibe recursos puntuales por correo (paso opcional).

Whatsapp Mentores Tech