Todo lo que hemos visto hasta ahora ha sido conceptual: qué es un microservicio, qué se gana y qué se paga, cómo se compara con el monolito y cuándo conviene dar el paso. A partir de aquí, el curso se vuelve práctico, y para que lo práctico tenga sentido necesitamos un caso realista que nos acompañe de principio a fin. Ese caso es TechCorp y su tienda online, techcorp-shop.

En esta lección presentamos el hilo conductor con todo detalle: quién es TechCorp y quiénes son las personas que tomarán las decisiones, cómo es su monolito actual, qué problemas concretos sufre, cuál es el flujo de negocio central que usaremos una y otra vez ("un cliente hace un pedido"), un fragmento real del código actual que servirá de punto de partida, el mapa de servicios que construiremos, el stack tecnológico elegido y una hoja de ruta que explica qué avanzará cada módulo sobre este caso. No vamos a diseñar todavía los límites de los servicios (eso es trabajo del módulo 2) ni a implementar nada (módulo 4): aquí solo fijamos el escenario y las reglas del juego.

Contenido

  1. Quién es TechCorp
  2. La tienda hoy: un monolito Node.js/Express con una única PostgreSQL
  3. Las seis áreas funcionales
  4. Los problemas concretos que sufre TechCorp
  5. El flujo central: "un cliente hace un pedido"
  6. Un fragmento del monolito actual: crearPedido
  7. El mapa objetivo de servicios
  8. El stack tecnológico elegido y por qué
  9. Hoja de ruta del caso a lo largo del curso
  10. Errores comunes y consejos
  11. Ejercicios
  12. Conclusión

  1. Quién es TechCorp

TechCorp es una empresa ficticia de comercio electrónico que vende productos de electrónica de consumo (auriculares, altavoces, accesorios, pequeños dispositivos) a través de su tienda online techcorp-shop. Todos los datos que aparecerán en el curso (clientes, productos, importes, pedidos) son inventados.

Datos de contexto que iremos usando:

Aspecto Situación
Antigüedad de la tienda Unos siete años en producción
Volumen habitual Del orden de 3.000 pedidos diarios en un día normal
Picos Black Friday y rebajas de enero: navegación por el catálogo multiplicada por 20, pedidos por 3-4
Equipo técnico Unas 25 personas: desarrollo, QA y sistemas
Organización actual Un "equipo de back-end", un "equipo de front-end" y un "equipo de sistemas"; el back-end empieza a organizarse informalmente por áreas

Dos personas aparecerán constantemente:

  • Marta, CTO de TechCorp. Es quien decide la estrategia técnica, quien defiende (o no) las inversiones ante dirección y quien ha llegado a la conclusión, tras aplicar los criterios de la lección anterior, de que la tienda necesita evolucionar hacia microservicios de forma incremental. Marta pondrá las restricciones de negocio: no se puede parar la tienda, no hay presupuesto ilimitado, cada paso tiene que aportar valor.
  • Luis, líder del equipo de Pedidos. Es el responsable del área más delicada de la tienda (donde se cruzan clientes, catálogo, stock, pagos y notificaciones) y será nuestro protagonista técnico: la mayor parte del código que escribiremos en el curso será el de servicio-pedidos, y muchas decisiones las veremos desde su punto de vista.

  1. La tienda hoy: un monolito Node.js/Express con una única PostgreSQL

techcorp-shop es un único proyecto Node.js 20 con Express, escrito en JavaScript, que se ejecuta como un solo proceso (replicado en tres servidores idénticos detrás de un balanceador) y que utiliza una única base de datos PostgreSQL con todas las tablas de todas las áreas.

Estructura simplificada del repositorio actual:

techcorp-shop/
├── servidor.js               # arranca Express y registra todas las rutas
├── rutas/
│   ├── clientes.js
│   ├── catalogo.js
│   ├── inventario.js
│   ├── pedidos.js
│   ├── pagos.js
│   └── notificaciones.js
├── controladores/
│   ├── clientesControlador.js
│   ├── catalogoControlador.js
│   ├── pedidosControlador.js     # aquí vive crearPedido
│   └── ...
├── bd/
│   ├── conexion.js               # un único pool de PostgreSQL
│   └── migraciones/              # todas las tablas juntas
├── servicios/
│   ├── correo.js                 # envío de emails
│   └── pasarelaPago.js           # llamada al proveedor de pagos
└── package.json

Y el esquema de la base de datos, muy resumido:

-- Todas en la misma base de datos "techcorp"
CREATE TABLE clientes        (id SERIAL PRIMARY KEY, email TEXT, nombre TEXT, direccion TEXT);
CREATE TABLE productos       (id SERIAL PRIMARY KEY, nombre TEXT, precio NUMERIC(10,2), categoria TEXT, activo BOOLEAN);
CREATE TABLE stock           (producto_id INT REFERENCES productos(id), cantidad INT, reservado INT);
CREATE TABLE pedidos         (id SERIAL PRIMARY KEY, cliente_id INT REFERENCES clientes(id), estado TEXT, total NUMERIC(10,2), creado_en TIMESTAMP);
CREATE TABLE lineas_pedido   (pedido_id INT REFERENCES pedidos(id), producto_id INT REFERENCES productos(id), cantidad INT, precio_unitario NUMERIC(10,2));
CREATE TABLE pagos           (id SERIAL PRIMARY KEY, pedido_id INT REFERENCES pedidos(id), importe NUMERIC(10,2), estado TEXT, referencia_pasarela TEXT);
CREATE TABLE notificaciones  (id SERIAL PRIMARY KEY, cliente_id INT, tipo TEXT, enviada_en TIMESTAMP);

Fíjate en las claves foráneas cruzadas entre áreas (pedidos.cliente_id → clientes, lineas_pedido.producto_id → productos, pagos.pedido_id → pedidos). Hoy son una comodidad enorme; en el módulo 2 veremos que son también el principal obstáculo para separar los datos.

  1. Las seis áreas funcionales

El monolito agrupa seis áreas de negocio, que hoy son carpetas y tablas dentro del mismo proyecto y que mañana serán servicios:

Área Qué hace hoy Tablas principales
Clientes Registro, inicio de sesión, perfil, direcciones de envío. clientes
Catálogo Fichas de producto, categorías, precios, búsqueda. productos
Inventario Cantidades disponibles por producto, reservas al hacer pedido, entradas de almacén. stock
Pedidos Creación y ciclo de vida del pedido (pendiente, confirmado, cancelado, enviado). pedidos, lineas_pedido
Pagos Cobro a través de la pasarela externa, registro de pagos y devoluciones. pagos
Notificaciones Envío de correos y SMS al cliente (confirmación, envío, incidencias). notificaciones

Estas seis áreas se corresponderán, una a una, con los seis servicios del mapa objetivo. Que la correspondencia sea tan directa es una simplificación deliberada para el curso; en la vida real, encontrar los límites correctos es un trabajo en sí mismo, que abordaremos en el módulo 2.

  1. Los problemas concretos que sufre TechCorp

Marta no quiere microservicios por moda. Los quiere porque la tienda tiene problemas medibles que encajan con las señales de la lección 01-04:

  1. Despliegues semanales con miedo. Toda la tienda se despliega los jueves por la noche. La suite de pruebas tarda 40 minutos; el despliegue, con comprobaciones manuales, dos horas. En el último trimestre, cuatro de doce despliegues se revirtieron total o parcialmente. Cualquier corrección urgente espera al jueves siguiente o requiere un despliegue de emergencia de toda la aplicación.

  2. Caídas en campañas. En el último Black Friday, el tráfico de navegación por el catálogo saturó los tres servidores. Como el catálogo comparte proceso y base de datos con todo lo demás, la creación de pedidos y los cobros también se cayeron: la tienda no vendió durante 50 minutos en el día de más ventas del año. Para evitarlo, sistemas replicó todo el monolito a diez servidores durante la campaña, pagando por capacidad de pagos y clientes que no hacía falta.

  3. Un equipo pisándose. Los desarrolladores de las distintas áreas trabajan sobre el mismo repositorio y las mismas tablas. Cuando el equipo de Notificaciones cambió una consulta sobre pedidos para un nuevo correo, rompió un informe de Pedidos. Cuando Pedidos añadió una columna a lineas_pedido, la migración falló en producción por un bloqueo con una consulta pesada de Catálogo. Los pull requests se atascan por conflictos, y el equipo de Luis calcula que dedica un 20 % del tiempo a coordinarse con otros equipos.

  4. Incidentes que se propagan. Un mes antes, un fallo del proveedor de correo hizo que el envío de emails empezara a acumular conexiones abiertas; la fuga de memoria terminó tumbando el proceso entero, incluidos los cobros.

  5. Modelo de datos del catálogo forzado. Los productos tienen atributos muy variables (unos tienen talla, otros voltaje, otros compatibilidad) y en PostgreSQL se ha acabado con una tabla atributos_producto genérica de clave-valor incómoda de consultar y de mantener.

Estos cinco problemas son el "porqué" de todo el curso. Cada módulo posterior resolverá alguno de ellos.

  1. El flujo central: "un cliente hace un pedido"

De todos los flujos de la tienda, uno los atraviesa todos: un cliente hace un pedido. Es el flujo que más valor tiene para el negocio, el que más áreas implica y el que más problemas concentra. Por eso será el ejemplo recurrente de todo el curso: lo modelaremos, lo dividiremos, lo implementaremos, lo desplegaremos, lo monitorizaremos y lo aseguraremos.

Los pasos, tal como ocurren hoy en el monolito:

  1. El cliente, ya identificado, envía su carrito (clienteId y una lista de productoId con cantidades).
  2. Se comprueba que el cliente existe y se recupera su dirección.
  3. Se consultan los productos para obtener nombre y precio actual.
  4. Se comprueba el stock de cada producto y se reserva (se incrementa stock.reservado).
  5. Se calcula el total y se crea el pedido en estado PENDIENTE con sus líneas.
  6. Se cobra llamando a la pasarela de pago externa y se registra el pago.
  7. Si el cobro va bien, el pedido pasa a CONFIRMADO, el stock reservado se descuenta definitivamente y se envía el correo de confirmación.
  8. Si el cobro falla, se libera la reserva de stock, el pedido pasa a CANCELADO y se envía un correo de incidencia.

Todo esto ocurre dentro de una única petición HTTP y, casi todo, dentro de una única transacción de base de datos.

sequenceDiagram
    autonumber
    actor C as Cliente
    participant M as Monolito techcorp-shop
    participant BD as PostgreSQL (única)
    participant PP as Pasarela de pago (externa)
    participant SMTP as Servidor de correo (externo)

    C->>M: POST /pedidos {clienteId, lineas}
    M->>BD: BEGIN
    M->>BD: SELECT cliente
    M->>BD: SELECT productos (precio)
    M->>BD: UPDATE stock SET reservado = reservado + cantidad
    M->>BD: INSERT pedido (PENDIENTE) + lineas
    M->>PP: cobrar(total)
    alt cobro correcto
        PP-->>M: OK, referencia
        M->>BD: INSERT pago; UPDATE pedido = CONFIRMADO; UPDATE stock (descontar)
        M->>BD: COMMIT
        M->>SMTP: enviar correo de confirmación
        M-->>C: 201 Created {pedidoId, estado: CONFIRMADO}
    else cobro rechazado
        PP-->>M: rechazado
        M->>BD: ROLLBACK (deshace reserva y pedido)
        M->>SMTP: enviar correo de incidencia
        M-->>C: 402 Payment Required
    end

Cuando la tienda esté dividida en servicios, este mismo flujo se convertirá en una coreografía de eventos: servicio-pedidos creará el pedido y publicará pedido.creado; servicio-inventario reservará stock y publicará stock.reservado; servicio-pagos cobrará y publicará pago.confirmado; servicio-pedidos confirmará el pedido y publicará pedido.confirmado (o pedido.cancelado si algo falla); y servicio-notificaciones enviará el correo. Esa versión la diseñaremos en el módulo 2 y la construiremos en el 4; de momento, quédate con la versión monolítica y con los nombres de los eventos, que reaparecerán constantemente:

Evento Quién lo publica Qué significa
pedido.creado servicio-pedidos Se ha registrado un pedido en estado PENDIENTE.
stock.reservado servicio-inventario El stock de las líneas del pedido ha quedado reservado.
pago.confirmado servicio-pagos La pasarela ha aceptado el cobro.
pedido.confirmado servicio-pedidos El pedido está completo: stock y pago correctos.
pedido.cancelado servicio-pedidos El pedido no ha podido completarse (sin stock, pago rechazado...).

  1. Un fragmento del monolito actual: crearPedido

Este es, simplificado pero fiel al espíritu del código real, el controlador Express que hoy implementa el flujo anterior. Léelo con calma: es el punto de partida de todo el curso, y volveremos sobre él para descomponerlo (módulo 2), extraer servicios (módulo 4) y compararlo con el resultado final (módulo 8).

// controladores/pedidosControlador.js  (monolito techcorp-shop, versión actual)
const bd = require('../bd/conexion');            // único pool de PostgreSQL
const pasarelaPago = require('../servicios/pasarelaPago');
const correo = require('../servicios/correo');

async function crearPedido(req, res) {
  const { clienteId, lineas } = req.body;         // lineas: [{ productoId, cantidad }]
  const cliente = await bd.conectar();            // una conexión para toda la operación

  try {
    await cliente.query('BEGIN');

    // 1. Datos del cliente (tabla de OTRA área: clientes)
    const { rows: [datosCliente] } = await cliente.query(
      'SELECT id, email, nombre FROM clientes WHERE id = $1', [clienteId]);
    if (!datosCliente) throw new Error('CLIENTE_NO_EXISTE');

    // 2. Precios actuales (tabla de OTRA área: catálogo)
    const ids = lineas.map(l => l.productoId);
    const { rows: productos } = await cliente.query(
      'SELECT id, nombre, precio FROM productos WHERE id = ANY($1) AND activo = true', [ids]);
    if (productos.length !== ids.length) throw new Error('PRODUCTO_NO_DISPONIBLE');

    // 3. Comprobar y reservar stock (tabla de OTRA área: inventario)
    let total = 0;
    for (const linea of lineas) {
      const producto = productos.find(p => p.id === linea.productoId);
      const { rowCount } = await cliente.query(
        `UPDATE stock SET reservado = reservado + $1
          WHERE producto_id = $2 AND cantidad - reservado >= $1`,
        [linea.cantidad, linea.productoId]);
      if (rowCount === 0) throw new Error('SIN_STOCK');
      total += producto.precio * linea.cantidad;
    }

    // 4. Crear el pedido y sus líneas (tablas propias del área de pedidos)
    const { rows: [pedido] } = await cliente.query(
      `INSERT INTO pedidos (cliente_id, estado, total, creado_en)
       VALUES ($1, 'PENDIENTE', $2, NOW()) RETURNING id`, [clienteId, total]);
    for (const linea of lineas) {
      const producto = productos.find(p => p.id === linea.productoId);
      await cliente.query(
        `INSERT INTO lineas_pedido (pedido_id, producto_id, cantidad, precio_unitario)
         VALUES ($1, $2, $3, $4)`, [pedido.id, linea.productoId, linea.cantidad, producto.precio]);
    }

    // 5. Cobrar (llamada síncrona a un proveedor externo, en medio de la transacción)
    const resultadoCobro = await pasarelaPago.cobrar({ importe: total, clienteId, pedidoId: pedido.id });
    if (!resultadoCobro.ok) throw new Error('PAGO_RECHAZADO');

    // 6. Registrar pago y confirmar (tabla de OTRA área: pagos)
    await cliente.query(
      `INSERT INTO pagos (pedido_id, importe, estado, referencia_pasarela)
       VALUES ($1, $2, 'CONFIRMADO', $3)`, [pedido.id, total, resultadoCobro.referencia]);
    await cliente.query(`UPDATE pedidos SET estado = 'CONFIRMADO' WHERE id = $1`, [pedido.id]);
    for (const linea of lineas) {
      await cliente.query(
        `UPDATE stock SET cantidad = cantidad - $1, reservado = reservado - $1 WHERE producto_id = $2`,
        [linea.cantidad, linea.productoId]);
    }

    await cliente.query('COMMIT');

    // 7. Enviar email (área de notificaciones), fuera de la transacción pero en la misma petición
    await correo.enviar({
      para: datosCliente.email,
      asunto: `Pedido ${pedido.id} confirmado`,
      cuerpo: `Hola ${datosCliente.nombre}, tu pedido por ${total} € está confirmado.`
    });

    return res.status(201).json({ pedidoId: pedido.id, estado: 'CONFIRMADO', total });

  } catch (error) {
    await cliente.query('ROLLBACK');
    const codigos = { CLIENTE_NO_EXISTE: 404, PRODUCTO_NO_DISPONIBLE: 400, SIN_STOCK: 409, PAGO_RECHAZADO: 402 };
    return res.status(codigos[error.message] || 500).json({ error: error.message });
  } finally {
    cliente.liberar();
  }
}

module.exports = { crearPedido };

Qué observar en este código, porque cada punto será un tema del curso:

  • Una función hace seis cosas de cinco áreas distintas: valida cliente, consulta catálogo, reserva inventario, crea pedido, cobra y notifica. Es fácil de leer, pero cualquier cambio en cualquier área pasa por aquí.
  • Acceso directo a tablas de otras áreas (clientes, productos, stock, pagos). Es lo que hace imposible que Notificaciones cambie su esquema sin avisar a Pedidos, y viceversa. La lección 02-04 tratará precisamente de romper esto.
  • Una transacción lo protege todo: si el pago falla, el ROLLBACK deshace la reserva de stock y el pedido. Es la comodidad que perderemos al separar bases de datos y que la lección 02-05 sustituirá con una saga.
  • Una llamada externa (la pasarela de pago) dentro de la transacción: mientras la pasarela responde (a veces segundos), las filas de stock quedan bloqueadas para todos los demás pedidos. En campañas, esto contribuye a la saturación.
  • El envío de correo es síncrono: si el servidor de correo tarda o falla, la respuesta al cliente tarda o falla, aunque el pedido esté perfectamente cobrado. Esto es lo que las notificaciones asíncronas por eventos resolverán en el módulo 3.
  • Sin idempotencia: si el cliente pulsa dos veces "comprar", se crean dos pedidos y se cobra dos veces. Hoy lo evita el front-end; en un sistema distribuido, no será suficiente.

  1. El mapa objetivo de servicios

Este es el sistema que iremos construyendo. Los nombres, puertos y bases de datos son fijos para todo el curso; los reutilizaremos en el código, en los ficheros de Docker Compose y en los manifiestos de Kubernetes.

Servicio Puerto Responsabilidad Base de datos
servicio-clientes 3004 Registro, autenticación de clientes (delegada en Keycloak), perfil y direcciones. PostgreSQL (clientes)
servicio-catalogo 3001 Fichas de producto, categorías, precios, búsqueda. Alta lectura. MongoDB (catalogo)
servicio-inventario 3006 Stock disponible, reservas y liberaciones, entradas de almacén. PostgreSQL (inventario)
servicio-pedidos 3002 Creación y ciclo de vida del pedido; coordina el flujo mediante eventos. PostgreSQL (pedidos)
servicio-pagos 3003 Cobros contra la pasarela externa, registro de pagos y devoluciones. PostgreSQL (pagos)
servicio-notificaciones 3005 Envío de correos y SMS a partir de eventos de otros servicios. Sin base de datos propia relevante (cola de RabbitMQ y registro mínimo de envíos)
API Gateway 8080 Punto de entrada único: enrutado, autenticación JWT, límites de uso.

Y la infraestructura de apoyo que rodeará a los servicios:

Pieza Papel
RabbitMQ Broker de mensajes para los eventos pedido.creado, stock.reservado, pago.confirmado, pedido.confirmado, pedido.cancelado.
Keycloak Servidor de identidad (OAuth2 / OpenID Connect) que emite los JWT que el gateway y los servicios validan.
Prometheus, Grafana, Loki Métricas, paneles y logs centralizados.
OpenTelemetry + Jaeger Trazas distribuidas para seguir un pedido a través de todos los servicios.
Docker / Docker Compose Empaquetado y entorno local de desarrollo.
Kubernetes (+ Istio) Orquestación en producción y malla de servicios.
GitHub Actions Pipelines de integración y despliegue continuo.
flowchart TB
    Cliente[Navegador / App móvil] --> GW[API Gateway :8080]
    KC[Keycloak] -. JWT .-> GW
    GW --> CLI[servicio-clientes :3004]
    GW --> CAT[servicio-catalogo :3001]
    GW --> PED[servicio-pedidos :3002]
    CLI --> BD1[(PG clientes)]
    CAT --> BD2[(MongoDB)]
    PED --> BD3[(PG pedidos)]
    INV[servicio-inventario :3006] --> BD4[(PG inventario)]
    PAG[servicio-pagos :3003] --> BD5[(PG pagos)]
    NOT[servicio-notificaciones :3005]
    PED <-. eventos .-> MQ[(RabbitMQ)]
    MQ <-. eventos .-> INV
    MQ <-. eventos .-> PAG
    MQ -. eventos .-> NOT
    PAG --> PP[Pasarela de pago externa]
    NOT --> SMTP[Correo / SMS externo]

  1. El stack tecnológico elegido y por qué

Marta y los líderes de equipo han fijado el stack con dos criterios: continuidad con lo que el equipo ya conoce (para no aprender un lenguaje nuevo a la vez que una arquitectura nueva) y estándares de mercado para el resto de piezas.

Decisión Elección Por qué
Lenguaje y framework de los servicios Node.js 20 + Express (JavaScript) Es lo que ya usa el monolito; el equipo lo domina. Los microservicios permitirían otros lenguajes, pero TechCorp no tiene hoy una razón para ello. Identificadores en español (crearPedido, PedidoRepositorio, clienteId) por coherencia con el código existente.
Base de datos relacional PostgreSQL (una por servicio) Ya se conoce y se opera; encaja con pedidos, pagos, inventario y clientes, donde importan las transacciones locales.
Base de datos del catálogo MongoDB Resuelve el problema real de los atributos variables de producto. Es el único caso de heterogeneidad justificada.
Mensajería RabbitMQ Broker maduro, sencillo de operar a la escala de TechCorp, con soporte de confirmaciones y colas de errores.
Empaquetado y entorno local Docker y Docker Compose Estándar de facto; permite levantar toda la tienda en un portátil.
Orquestación Kubernetes Estándar de facto para operar contenedores en producción; el equipo de sistemas ya lo ha probado.
CI/CD GitHub Actions El código ya está en GitHub; se evita otra herramienta.
Observabilidad Prometheus, Grafana, Loki, OpenTelemetry, Jaeger Conjunto de código abierto ampliamente usado que cubre métricas, paneles, logs y trazas.
Seguridad JWT/OAuth2 con Keycloak Identidad centralizada y estándar; los servicios solo validan tokens.
Malla de servicios Istio Cifrado entre servicios, políticas y observabilidad de red sin tocar el código de los servicios. Se introduce al final, cuando el resto ya funciona.

Una nota importante para tu aprendizaje: estas elecciones son razonables, no las únicas. En la lección 04-01 discutiremos alternativas (Kafka frente a RabbitMQ, otros lenguajes, otros orquestadores). Aquí simplemente fijamos el terreno para que todos los ejemplos del curso sean coherentes.

  1. Hoja de ruta del caso a lo largo del curso

Así avanzará la historia de TechCorp módulo a módulo. Cada fila responde a la pregunta "¿qué le pasa a la tienda en este módulo?".

Módulo Qué avanza el caso de TechCorp Problema de TechCorp que ataca
1. Introducción (este) Se fija el escenario, el flujo central y el mapa objetivo. Marta decide migrar de forma incremental. Entender el porqué.
2. Diseño Se analizan las seis áreas, se definen sus límites (bounded contexts), se decide qué datos son de quién y cómo se sustituye la gran transacción de crearPedido por una saga basada en eventos. Equipos que se pisan; transacción única.
3. Comunicación Se diseñan las APIs REST de cada servicio, los eventos de RabbitMQ del flujo de pedido, el gateway en el 8080, cómo se encuentran los servicios y cómo se versionan los contratos. Acoplamiento entre áreas; correo síncrono.
4. Implementación Se construyen de verdad los servicios en Node.js/Express, empezando por servicio-pedidos con Luis: configuración, consumo de APIs, publicación de eventos y pruebas (unitarias, de integración, de contrato). Punto de partida real del código.
5. Despliegue Se empaquetan los servicios en Docker, se levanta la tienda con Docker Compose y luego en Kubernetes, se montan pipelines en GitHub Actions y se despliega servicio-catalogo en canary. Se añade Istio. Despliegues semanales con miedo.
6. Monitoreo Se instrumentan métricas, logs y trazas del flujo de pedido; se diseñan reintentos, circuit breakers y colas de errores; se escala el catálogo para el Black Friday; se definen SLOs y alertas. Caídas en campañas; incidentes que se propagan.
7. Seguridad Se protege el gateway con JWT de Keycloak, se cifra la comunicación entre servicios y se endurecen contenedores y clúster. Superficie de ataque de un sistema distribuido.
8. Casos de estudio Se recorre la migración completa de principio a fin (patrón strangler), se ve la implementación y el despliegue completos del sistema, y se extraen lecciones. Consolidar todo.
flowchart LR
    M1[M1<br/>Escenario] --> M2[M2<br/>Diseño de límites<br/>y datos] --> M3[M3<br/>APIs, eventos<br/>y gateway] --> M4[M4<br/>Código de los<br/>servicios]
    M4 --> M5[M5<br/>Docker, K8s,<br/>CI/CD] --> M6[M6<br/>Observabilidad<br/>y resiliencia] --> M7[M7<br/>Seguridad] --> M8[M8<br/>Migración completa<br/>y lecciones]

Un detalle que conviene tener presente desde ya: el curso no hace un "big bang". TechCorp no apagará el monolito un viernes para encender seis servicios el lunes. Los servicios se extraerán uno a uno, empezando por el catálogo (la razón de escalado más clara y el menor riesgo), después el flujo de pedidos, y el monolito irá adelgazando hasta desaparecer. Ese proceso incremental se detalla en la lección 08-01.

Errores Comunes y Consejos

  • Perder de vista el porqué. Cuando en el módulo 5 estés peleándote con un manifiesto de Kubernetes, recuerda los cinco problemas del apartado 4: cada pieza de infraestructura está ahí para resolver uno de ellos, no por sí misma.
  • Idealizar el punto de llegada. El mapa de servicios del apartado 7 es el objetivo, pero se construirá paso a paso, y algunas decisiones se revisarán por el camino (es lo normal en un proyecto real).
  • Despreciar el código del monolito. crearPedido es un código razonable para un monolito; no es "malo", es inadecuado para el problema que TechCorp tiene ahora. Entenderlo bien es la clave para descomponerlo bien.
  • Cambiar los nombres. Mantén los nombres de servicios, puertos y eventos exactamente como aparecen en las tablas de esta lección; el resto del curso los da por supuestos.
  • Consejo: guarda una copia mental (o real) del diagrama de secuencia del apartado 5. Lo compararás con su versión en eventos en el módulo 2 y con la traza distribuida real en el módulo 6, y esa comparación es una de las mejores formas de entender qué cambia con los microservicios.

Ejercicios

Ejercicio 1: Trazar el flujo

Sin mirar el diagrama de secuencia, escribe en orden los ocho pasos del flujo "un cliente hace un pedido" tal como ocurre hoy en el monolito, e indica para cada paso a qué área funcional pertenece.

Ejercicio 2: Leer crearPedido con ojos de arquitecto

Sobre el fragmento del apartado 6, responde:

  1. ¿Qué tablas consulta o modifica que no pertenecen al área de pedidos?
  2. ¿Qué ocurre si la pasarela de pago tarda 15 segundos en responder? ¿A quién afecta?
  3. ¿Qué ocurre si el envío del correo falla después del COMMIT? ¿Qué ve el cliente y qué queda en la base de datos?

Ejercicio 3: Relacionar problemas y módulos

Para cada uno de los cinco problemas del apartado 4, indica qué módulo (o módulos) del curso lo abordarán y con qué pieza del mapa objetivo o del stack se relaciona.

Soluciones

Ejercicio 1

  1. El cliente envía el carrito → Pedidos (punto de entrada).
  2. Comprobar cliente y recuperar dirección → Clientes.
  3. Consultar productos y precios → Catálogo.
  4. Comprobar y reservar stock → Inventario.
  5. Calcular total y crear pedido PENDIENTEPedidos.
  6. Cobrar en la pasarela y registrar el pago → Pagos.
  7. Confirmar pedido, descontar stock y enviar correo → Pedidos, Inventario y Notificaciones.
  8. Si el cobro falla: liberar reserva, cancelar y notificar incidencia → Inventario, Pedidos y Notificaciones.

Ejercicio 2

  1. clientes (área de clientes), productos (catálogo), stock (inventario) y pagos (pagos). Solo pedidos y lineas_pedido son propias.
  2. La transacción sigue abierta durante esos 15 segundos, con las filas de stock de esos productos bloqueadas por el UPDATE. Cualquier otro pedido que incluya alguno de esos productos se queda esperando. En una campaña, muchos pedidos esperando bloqueos agotan las conexiones y el sistema entero se degrada. Además, el cliente ve la página "cargando" durante 15 segundos.
  3. El pedido está confirmado, cobrado y con stock descontado en la base de datos (el COMMIT ya se ha ejecutado). Pero correo.enviar lanza una excepción, el catch ejecuta un ROLLBACK (que ya no deshace nada, porque la transacción terminó) y responde al cliente con un 500. El cliente cree que su compra ha fallado, aunque se le ha cobrado; probablemente vuelva a intentarlo y se le cobre dos veces. Es un ejemplo perfecto de por qué las notificaciones deben ser asíncronas y desacopladas.

Ejercicio 3

Problema Módulos Piezas relacionadas
Despliegues semanales con miedo 5 (Docker, Kubernetes, CI/CD, estrategias de despliegue) y 4 (pruebas por servicio) GitHub Actions, contenedores, despliegue canary
Caídas en campañas 6 (escalabilidad, resiliencia) y 2/3 (catálogo como servicio aparte) servicio-catalogo escalado independientemente, Prometheus/Grafana
Un equipo pisándose 2 (límites y una base de datos por servicio) y 3 (contratos) Bounded contexts, APIs versionadas
Incidentes que se propagan 3 (mensajería asíncrona) y 6 (gestión de errores, circuit breakers) RabbitMQ, servicio-notificaciones aislado
Modelo de datos del catálogo forzado 2 (una base de datos por servicio) y 4 (implementación) MongoDB en servicio-catalogo

Conclusión

En esta lección hemos presentado a fondo el caso que vertebra el curso: TechCorp, una tienda online que hoy es un monolito Node.js/Express sobre una única PostgreSQL con seis áreas funcionales, y que sufre problemas concretos y medibles: despliegues semanales temidos, caídas en campañas por saturación del catálogo, equipos que se pisan sobre el mismo código y las mismas tablas, incidentes que se propagan de áreas secundarias a las críticas y un modelo de datos forzado en el catálogo. Hemos recorrido paso a paso el flujo central "un cliente hace un pedido" y hemos leído el código real de crearPedido, que concentra en una sola función y una sola transacción el trabajo de cinco áreas: ese fragmento es nuestro punto de partida. Hemos fijado el mapa objetivo (seis servicios con sus puertos y bases de datos más un gateway), el stack tecnológico y sus razones, los cinco eventos del flujo de pedido y una hoja de ruta módulo a módulo.

Con el escenario definido, el módulo 2 empieza el trabajo de verdad: diseñar los microservicios. Partiremos de los principios de diseño, aprenderemos a descomponer el monolito de TechCorp, definiremos sus bounded contexts, decidiremos cómo repartir los datos entre servicios y sustituiremos la gran transacción de crearPedido por una saga coordinada mediante eventos. Marta ha tomado la decisión; a partir de ahora acompañamos a Luis y a su equipo en la ejecución.

Curso de Microservicios

Módulo 1: Introducción a los Microservicios

Módulo 2: Diseño de Microservicios

Módulo 3: Comunicación entre Microservicios

Módulo 4: Implementación de Microservicios

Módulo 5: Despliegue y Orquestación

Módulo 6: Monitoreo y Mantenimiento

Módulo 7: Seguridad en Microservicios

Módulo 8: Casos de Estudio y Ejemplos Prácticos

© Copyright 2026. Todos los derechos reservados