← Volver a todos los artículos
Retos

De Monolito a Microservicios: Una Guía Práctica para CTOs de Startups en Crecimiento

Por Marc Molas·1 de diciembre de 2024·10 min de lectura

Tu monolito te trajo hasta aquí. Permitió que un equipo pequeño entregara rápido, desplegara con un solo pipeline y depurara con un stack trace en vez de rastrear logs por cinco servicios distintos. Funcionó. Y si seguiste los principios de un monolito modular bien diseñado, te dio una base sólida.

Pero ahora algo ha cambiado. Tienes tres equipos trabajando sobre el mismo repositorio y los conflictos de merge son constantes. El módulo de procesamiento de pagos necesita escalar de forma diferente al de notificaciones. Un despliegue que debería tardar diez minutos tarda una hora porque hay que coordinar entre equipos. Un bug en el módulo de reporting bloquea el release de una funcionalidad de facturación que está lista desde hace una semana.

Estas son señales reales. Y la respuesta no es "reescribamos todo en microservicios este trimestre". La respuesta es evolucionar gradualmente.

Cuándo es realmente el momento de migrar

No migras porque los microservicios estén de moda. Migras porque el monolito se ha convertido en un cuello de botella para tu negocio. Estas son las señales concretas:

Múltiples equipos pisándose entre sí. Dos equipos tocan el mismo código, los PRs se bloquean mutuamente, y cada merge requiere coordinación que consume más tiempo que el desarrollo en sí. La ley de Conway empieza a hacer efecto: tu arquitectura necesita reflejar tu organización.

Necesidades de escalado divergentes. Tu API de búsqueda necesita escalar horizontalmente con el tráfico de usuarios, pero tu servicio de procesamiento de archivos necesita máquinas con más RAM y CPU. Escalas todo el monolito para satisfacer al componente más exigente, pagando infraestructura que el resto no necesita.

Despliegues demasiado largos y arriesgados. Un cambio de tres líneas requiere desplegar toda la aplicación. El pipeline de CI tarda 45 minutos. Y cada despliegue es un evento que genera ansiedad porque cualquier parte del sistema puede romperse.

Un fallo lo rompe todo. Un memory leak en el módulo de reporting tira abajo la API de clientes, el dashboard de administración y el sistema de facturación. No hay aislamiento de fallos.

Si reconoces dos o más de estas señales, es momento de planificar la migración. Si solo ves una, probablemente puedes resolver el problema con mejor modularización interna.

El Strangler Fig Pattern: no reescribas, extrae

La metáfora viene de la higuera estranguladora, una planta que crece alrededor de un árbol existente hasta que eventualmente lo reemplaza por completo. Tu monolito es el árbol. Los nuevos servicios son la higuera. Y la clave es que el árbol sigue vivo mientras la higuera crece.

No reescribes el monolito. Extraes servicios uno a uno, gradualmente, mientras el monolito sigue funcionando en producción. Cada extracción es un paso pequeño y controlado. Si algo sale mal, el monolito sigue ahí como fallback.

Paso 1: Identifica los límites

Antes de extraer nada, necesitas un mapa claro de los módulos de tu monolito y sus dependencias. Si diseñaste un monolito modular con bounded contexts bien definidos, esta parte es más sencilla. Si no, es el momento de hacerlo.

Busca las costuras naturales: módulos que se comunican con el resto a través de interfaces claras, que tienen su propio modelo de datos, que representan un dominio de negocio distinto. En términos de Domain-Driven Design, estás buscando bounded contexts.

Dibuja el grafo de dependencias. Identifica qué módulos dependen de cuáles. Los que tienen menos dependencias entrantes y salientes son los candidatos más fáciles para la extracción.

Paso 2: Extrae el módulo de mayor dolor primero

No empieces por el módulo más fácil ni por el más difícil. Empieza por el que más dolor causa. Normalmente es el que cumple una o más de estas condiciones:

  • Escala de forma diferente al resto del sistema.
  • Cambia con mucha frecuencia y genera conflictos con otros equipos.
  • Tiene requisitos tecnológicos distintos (necesita GPUs, una base de datos diferente, un runtime específico).
  • Sus fallos afectan desproporcionadamente al resto del sistema.

Extrae ese módulo como un servicio independiente. Despliégalo por separado. Dale su propio pipeline de CI/CD. Asígnale un equipo que sea su dueño.

Paso 3: Pon un API gateway o reverse proxy delante

Aquí es donde la magia del Strangler Fig ocurre. Colocas un API gateway (Kong, NGINX, AWS API Gateway, Traefik) delante de todo tu sistema. Las peticiones que antes iban directas al monolito ahora pasan por el gateway.

El gateway decide: esta petición va al nuevo servicio, esta otra sigue yendo al monolito. Puedes hacer el cambio gradualmente — empezar redirigiendo el 5% del tráfico al nuevo servicio, monitorizar, y subir progresivamente hasta el 100%.

Si el nuevo servicio falla, el gateway puede redirigir de vuelta al monolito. Migración sin riesgo existencial.

Paso 4: Mueve los datos (la parte más difícil)

Aquí es donde la mayoría de las migraciones se complican. Mientras tu nuevo servicio siga leyendo y escribiendo en la misma base de datos que el monolito, no tienes un microservicio real — tienes un monolito distribuido, que es lo peor de ambos mundos.

El objetivo es que cada servicio tenga su propia base de datos. El camino para llegar ahí:

  1. Dual writes. El nuevo servicio escribe en su propia base de datos Y en la del monolito durante un periodo de transición. Verificas que los datos son consistentes.
  2. Sincronización por eventos. Introduces un sistema de eventos (Kafka, RabbitMQ, SNS/SQS) para mantener sincronizados los datos entre el servicio y el monolito.
  3. Cutover. Cuando confías en que el nuevo servicio es la fuente de verdad, eliminas la escritura en la base de datos del monolito. Los demás módulos que necesiten esos datos los obtienen a través de la API del nuevo servicio o consumen sus eventos.

Acepta que habrá un periodo de eventual consistency. No intentes mantener transacciones ACID entre servicios — ese camino lleva a distributed transactions y two-phase commits, que son frágiles y lentos.

Paso 5: Repite

Extrae el siguiente servicio. Y el siguiente. Cada extracción debería tardar semanas, no meses. Si una extracción te está llevando tres meses, probablemente estás extrayendo un módulo demasiado grande o las dependencias no estaban tan claras como pensabas.

Con cada extracción, el monolito se hace más pequeño y más manejable. Eventualmente, lo que queda es un servicio más — o se descompone en los últimos dos o tres servicios de forma natural.

La infraestructura que necesitas

Microservicios no son solo código en repositorios separados. Necesitan infraestructura de soporte que no existía en tu mundo monolítico:

Service discovery. Los servicios necesitan encontrarse entre sí. Consul, DNS interno de Kubernetes, o el service discovery de tu cloud provider.

Logging centralizado. Con diez servicios, no puedes hacer SSH a cada máquina para leer logs. Necesitas ELK Stack, Datadog, Grafana Loki — un lugar donde todos los logs converjan.

Distributed tracing. Un request del usuario puede tocar cinco servicios. Sin tracing (Jaeger, Zipkin, Datadog APM), depurar un error es adivinar en qué servicio se originó. Implementa OpenTelemetry desde el primer servicio.

CI/CD por servicio. Cada servicio tiene su propio pipeline. Cambias el servicio de pagos, solo se despliega el servicio de pagos. GitHub Actions, GitLab CI o la herramienta que uses, pero independiente por servicio.

Monitorización y alertas. Health checks, métricas de latencia, tasas de error, saturación de recursos — por servicio. Si no puedes ver el estado de cada servicio en un dashboard, estás navegando a ciegas.

Lo que no debes hacer

No extraigas todo a la vez. La tentación de "hagamos la migración completa en un trimestre" es fuerte. Resiste. Cada extracción es un riesgo controlado. Diez extracciones simultáneas son caos.

No crees nano-servicios. Un servicio que solo tiene un endpoint y 200 líneas de código no debería ser un servicio. Tiene todo el overhead operativo de un microservicio sin ningún beneficio. Un servicio debe representar un dominio de negocio con sentido propio.

No empieces por el módulo más acoplado. Si el módulo de usuarios está entrelazado con todo el sistema, es el peor candidato para la primera extracción. Empieza por algo con menos dependencias.

No olvides el monitoreo. Cada servicio que extraes sin monitoreo adecuado es una caja negra en producción. Primero observabilidad, después extracción.

Estructura de equipos: cada servicio necesita un dueño

Un microservicio sin equipo responsable es un servicio huérfano. Y los servicios huérfanos acumulan deuda técnica a velocidad alarmante porque nadie se siente dueño de mantenerlos.

Cada servicio necesita un equipo que sea su dueño claro. Ese equipo decide su roadmap, gestiona sus despliegues, responde cuando falla a las tres de la mañana. No necesita ser un equipo dedicado exclusivamente a ese servicio — un equipo puede ser dueño de dos o tres servicios relacionados. Pero la propiedad tiene que ser explícita.

Esto es exactamente lo que describe la ley de Conway invertida: diseñas tu arquitectura para que refleje la estructura de equipos que quieres tener. Si quieres equipos autónomos que entreguen de forma independiente, necesitas servicios que se puedan desarrollar y desplegar de forma independiente.

La migración es un proceso, no un proyecto

La migración de monolito a microservicios no tiene una fecha de fin en un Gantt chart. Es un proceso continuo que evoluciona con tu organización. Extraes servicios cuando el dolor lo justifica, no porque haya un plan que dice que toca.

En Conectia, trabajamos con startups europeas que están exactamente en este punto: el monolito les sirvió para llegar a product-market fit, y ahora necesitan evolucionar la arquitectura para escalar. Los ingenieros senior y arquitectos de LATAM que proporcionamos han guiado esta transición múltiples veces — saben qué extraer primero, cómo evitar los errores clásicos de las migraciones distribuidas, y cómo hacerlo sin parar la entrega de funcionalidades.

Porque esa es la clave: tu negocio no puede parar mientras migras. Los usuarios siguen usando el producto. El equipo de producto sigue pidiendo funcionalidades. La migración tiene que ocurrir en paralelo a todo eso. Y eso requiere ingenieros que hayan hecho esto antes.


¿Tu monolito se está convirtiendo en un cuello de botella? Habla con un CTO — te conectamos con arquitectos senior que han guiado esta transición sin parar la entrega.

¿Listo para construir tu equipo de ingeniería?

Habla con un partner técnico y despliega ingenieros validados por CTOs en 72 horas.