Microservicios
Una arquitectura de microservicios divide la aplicación en servicios pequeños, desplegables por separado y comunicados por red.
Es una decisión con consecuencias enormes y difíciles de revertir, así que este capítulo empieza por la parte que casi nunca se cuenta: por qué probablemente no los necesitas.
Qué problema resuelven de verdad
La respuesta habitual es "escalabilidad". Suele ser falsa: un monolito bien hecho escala horizontalmente sin problema, y muchas aplicaciones grandes funcionan así.
El problema que resuelven de verdad es organizativo. Cuando tienes ochenta desarrolladores tocando el mismo repositorio, coordinar releases se convierte en el cuello de botella. Los microservicios permiten que quince equipos desplieguen sin pedirse permiso.
Es la ley de Conway aplicada a propósito: la arquitectura acaba pareciéndose a la estructura de tu organización, así que más vale elegir la estructura antes.
Si tienes menos de veinte desarrolladores, es muy probable que no tengas ese problema.
Lo que cuestan
| Con un monolito | Con microservicios |
|---|---|
| Una llamada a función | Una llamada de red que puede fallar |
| Una transacción de base de datos | Consistencia eventual y compensaciones |
| Un despliegue | Docenas, coordinados |
| Un log | Trazas distribuidas o no te enteras de nada |
| Refactorizar entre módulos | Cambiar un contrato entre equipos |
Fíjate en la segunda fila, que es la que más duele. En un monolito, "cobrar y reservar stock" es una transacción: o pasan las dos cosas o ninguna. Repartido en dos servicios, eso deja de existir y tienes que construirlo a mano.
Y en la cuarta: sin trazas distribuidas, depurar una petición que atraviesa seis servicios es imposible. La observabilidad deja de ser recomendable y pasa a ser un requisito.
Cuándo NO usarlos
Señales bastante fiables de que te vas a arrepentir:
- El equipo es pequeño. Menos de quince o veinte personas: el coste de coordinación que resuelven no lo tienes.
- No tienes observabilidad. Sin trazas y logs centralizados, cada incidente será una investigación a ciegas.
- No tienes CI/CD sólido. Si desplegar un servicio es manual, desplegar veinte es inviable.
- El dominio no está claro. Si aún no sabes dónde están las fronteras del negocio, las vas a poner mal — y mover una frontera entre servicios cuesta muchísimo más que mover un módulo.
- Lo haces porque lo hace Netflix. Netflix tiene problemas que tú no tienes, y equipos de plataforma que tú tampoco.
La alternativa razonable: el monolito modular
Un monolito con fronteras internas bien definidas te da casi todas las ventajas organizativas sin la complejidad operativa:
mi-app/
├── facturacion/ ← módulos con fronteras claras
├── inventario/ ← se comunican por interfaces explícitas
└── usuarios/ ← comparten proceso y base de datos
Y tiene una propiedad valiosa: si un día de verdad necesitas separar, ya sabes por dónde cortar. Es mucho más fácil extraer un servicio de un monolito modular que arreglar unos microservicios mal divididos.
Empieza aquí. Separa cuando el dolor sea real y puedas señalarlo con el dedo.
Cómo dividir
Si decides seguir adelante, la división correcta es por dominio de negocio, no por capa técnica:
❌ Por capa ✅ Por dominio
servicio-de-frontend pedidos
servicio-de-backend pagos
servicio-de-base-de-datos inventario
La prueba práctica: si un cambio de negocio típico obliga a tocar tres servicios y coordinar tres despliegues, la división está mal. Cada servicio debería poder cambiar y desplegarse solo.
Los patrones que vas a necesitar
Base de datos por servicio
Cada servicio es dueño de sus datos, y nadie más los toca directamente.
Es incómodo — se acabaron los JOIN entre dominios — pero es lo que hace posible desplegar por separado. Si dos servicios comparten tablas, están acoplados por la base de datos y no ganas nada.
Circuit breaker
Sin él, un servicio lento tumba a todos los que dependen de él: las peticiones se acumulan esperando y agotan los hilos disponibles. Es el fallo en cascada.
El patrón corta la comunicación cuando detecta fallos repetidos:
CERRADO ──(muchos fallos)──> ABIERTO ──(pasa un tiempo)──> SEMIABIERTO
↑ │
└──────────────────(la prueba funciona)──────────────────────┘
Abierto, falla de inmediato en lugar de esperar. Eso protege al que llama y da respiro al que está caído.
Va siempre acompañado de timeouts agresivos (una llamada sin timeout es una bomba de relojería) y reintentos con espera creciente y aleatoria — sin la parte aleatoria, todos los clientes reintentan a la vez y rematan al servicio que intentaba recuperarse.
Saga
Sustituye a la transacción distribuida, que en la práctica no existe. Una secuencia de pasos locales, cada uno con su compensación:
Reservar stock → Cobrar → Enviar
↓ ↓
liberar stock devolver
Si falla el envío, se ejecutan las compensaciones hacia atrás. Con una diferencia importante respecto a una transacción: no es un rollback. El cobro ocurrió y la devolución también; ambos quedan en el histórico. El sistema es correcto, pero el modelo de negocio tiene que aceptarlo.
API Gateway
Un único punto de entrada para los clientes, que se encarga del enrutado, la autenticación y los límites de peticiones. Evita que cada cliente tenga que conocer la topología interna, y que cada servicio implemente la autenticación por su cuenta.
Comunicación
Síncrona (HTTP, gRPC) — simple y directa, pero acopla: si el que responde está caído, el que llama falla. Úsala cuando necesites la respuesta para continuar.
Asíncrona (colas, eventos) — el emisor publica y sigue. Desacopla de verdad y absorbe picos, a cambio de consistencia eventual y de que depurar sea más difícil. Úsala para todo lo que pueda esperar.
La regla práctica: síncrono solo cuando de verdad necesitas la respuesta ahora. Un pedido no necesita esperar a que se envíe el email de confirmación.
Lo que necesitas antes de empezar
Una lista honesta de requisitos previos:
- ✅ CI/CD automatizado, por servicio
- ✅ Contenedores y algún tipo de orquestación
- ✅ Trazas distribuidas y logs centralizados
- ✅ Un catálogo de servicios y sus dueños
- ✅ Contratos de API versionados y con compatibilidad hacia atrás
- ✅ Entorno de desarrollo local que no obligue a levantar veinte servicios
Si te faltan tres o más, resuélvelos antes. Son más baratos de montar con un monolito que en medio de una migración.
Resumen
- Los microservicios resuelven un problema organizativo, no técnico
- Con menos de veinte desarrolladores, probablemente no tienes ese problema
- Lo que más duele es perder la transacción de base de datos
- El monolito modular da las ventajas sin la complejidad, y te enseña por dónde cortar
- Divide por dominio de negocio, nunca por capa técnica
- Timeouts, circuit breakers y reintentos con aleatoriedad no son opcionales
- Asíncrono por defecto; síncrono solo si necesitas la respuesta ya
- Sin observabilidad, no empieces
Recursos adicionales
- Microservices.io — el catálogo de patrones de referencia
- MonolithFirst, de Martin Fowler
- Monitorización y observabilidad — requisito previo
- Curso de Kubernetes
💡 Recuerda: los microservicios cambian complejidad de código por complejidad de operación. Asegúrate de que ese cambio te compensa.
En el próximo capítulo cerramos el curso con la disciplina que mide si todo esto funciona.