Llegamos al final del curso, y nada consolida mejor lo aprendido que diseñar un sistema completo desde cero aplicando, de forma justificada, las decisiones que hemos ido estudiando. En esta lección actuaremos como el equipo de arquitectura de una empresa ficticia, MercadoFiatc, que necesita construir una plataforma de comercio electrónico. Partiremos de los requisitos de negocio, los traduciremos en atributos de calidad, elegiremos un estilo arquitectónico con su justificación, modelaremos los datos, definiremos despliegue y observabilidad, y registraremos las decisiones clave como ADR. No buscamos "la" respuesta correcta —en arquitectura casi nunca existe—, sino mostrar un razonamiento coherente: cada decisión se deriva de un requisito y asume conscientemente sus compromisos. Este caso cierra el curso integrando los módulos sobre estilos, datos, comunicación, despliegue, gobernanza y evolución.

Contenido

  1. Requisitos de MercadoFiatc
  2. De requisitos a atributos de calidad
  3. Elección del estilo arquitectónico
  4. Diagrama C4 del sistema
  5. Diseño de datos
  6. Comunicación entre componentes
  7. Despliegue
  8. Observabilidad
  9. Decisiones registradas (ADR) y evolución
  10. Errores Comunes y Consejos
  11. Ejercicios
  12. Conclusión del curso

  1. Requisitos de MercadoFiatc

El negocio nos plantea estos requisitos funcionales y restricciones:

  • Catálogo de productos navegable y con búsqueda, decenas de miles de referencias.
  • Carrito de la compra y proceso de pago (checkout) con pasarela externa.
  • Gestión de pedidos y su estado (confirmado, preparando, enviado, entregado).
  • Recomendaciones de productos.
  • Picos de tráfico muy fuertes en campañas (Black Friday): la navegación del catálogo puede multiplicarse por 50, mientras pagos crece mucho menos.
  • Equipo de unas 25 personas, organizado en 4 squads.
  • Presupuesto operativo limitado: no se quiere pagar la complejidad de lo distribuido donde no aporte.

  1. De requisitos a atributos de calidad

El primer paso de cualquier arquitectura seria es traducir requisitos de negocio en atributos de calidad medibles, porque son ellos —y no las funcionalidades— los que más condicionan el diseño.

Requisito de negocio Atributo de calidad Objetivo medible
Picos de campaña en catálogo Escalabilidad (granular) Catálogo escala x50 sin tocar pagos
El pago no puede caerse Disponibilidad 99,95% en checkout
Navegación fluida Rendimiento p95 de catálogo < 200 ms
Equipo de 4 squads autónomos Mantenibilidad / autonomía Squads despliegan sin coordinarse
Presupuesto limitado Coste operativo Minimizar piezas distribuidas
Datos de pedidos fiables Consistencia Pedido y pago consistentes (transaccional donde toca)

Observa la tensión clave: necesitamos escalado granular (catálogo crece mucho más que pagos) y autonomía de squads, lo que empuja hacia microservicios; pero el coste operativo limitado y la consistencia del pedido empujan hacia el monolito. La arquitectura nacerá de equilibrar esas fuerzas.

  1. Elección del estilo arquitectónico

No saltamos directamente a "microservicios para todo". Evaluamos opciones:

Estilo A favor para MercadoFiatc En contra
Monolito modular Bajo coste, consistencia fácil, refactor barato No permite escalar catálogo aparte ni autonomía total de squads
Microservicios completos Escalado granular y autonomía máxima Coste operativo alto, consistencia compleja, sobreingeniería al inicio
Mixto: monolito modular + pocos servicios extraídos Captura escalado donde importa, sin pagar todo el coste Requiere disciplina de fronteras

Elegimos el enfoque mixto y evolutivo, totalmente alineado con lo aprendido: empezamos con un monolito modular bien delimitado por dominios (Catálogo, Carrito, Pedidos, Pagos, Recomendaciones) y extraemos como microservicio solo lo que tenga necesidades de escalado o disponibilidad dispares. En concreto:

  • Catálogo se extrae pronto: es el que sufre el x50 en campaña y conviene escalarlo solo.
  • Recomendaciones se extrae: es opcional, puede fallar sin romper la compra y evoluciona rápido.
  • Carrito, Pedidos y Pagos permanecen juntos en el monolito modular al principio, porque comparten transacciones y consistencia fuerte; extraerlos pronto traería sagas y dolor sin beneficio claro.

Esta decisión aplica directamente la regla MonolithFirst y el patrón Strangler Fig: el monolito modular es el punto de partida, y la extracción es incremental y guiada por dolor real.

  1. Diagrama C4 del sistema

Usamos el modelo C4 (Contexto, Contenedores, Componentes, Código) para comunicar el diseño a distintas audiencias. Mostramos el nivel de Contenedores, el más útil para arquitectura.

graph TD
    Cliente[Cliente web/móvil] --> GW[API Gateway / Strangler Facade]
    GW --> Cat[Servicio Catálogo\nextraído, escala x50]
    GW --> Rec[Servicio Recomendaciones\nextraído, opcional]
    GW --> Mono[Monolito Modular\nCarrito + Pedidos + Pagos]
    Mono --> Pasarela[Pasarela de pago externa]
    Cat --> DBCat[(BD Catálogo)]
    Rec --> DBRec[(BD Recomendaciones)]
    Mono --> DBMono[(BD principal:\nCarrito, Pedidos, Pagos)]
    Mono -->|evento PedidoConfirmado| Broker[(Broker de mensajería)]
    Broker --> Rec

Leamos el diagrama, que sintetiza casi todas las decisiones:

  • El API Gateway actúa también de Strangler Facade: enruta cada petición al servicio extraído o al monolito. Es el punto desde el que seguiremos estrangulando si hace falta.
  • Catálogo y Recomendaciones son contenedores independientes con su propia base de datos: pueden escalarse y desplegarse por separado.
  • El monolito modular agrupa Carrito, Pedidos y Pagos sobre una única base de datos, permitiendo transacciones ACID locales en el checkout.
  • La comunicación con Recomendaciones es asíncrona por eventos (PedidoConfirmado vía broker): así el pedido no depende de que Recomendaciones esté disponible.

  1. Diseño de datos

Aplicamos el principio una base de datos por servicio donde hay servicios separados, y consistencia fuerte donde la transacción lo exige:

Componente Almacén Justificación
Catálogo Motor con búsqueda (p. ej. PostgreSQL + índice de texto, o Elasticsearch para búsqueda avanzada) Lecturas masivas y búsqueda; tolera réplicas de lectura
Recomendaciones Almacén propio (puede ser NoSQL) Datos derivados, esquema flexible, no transaccional
Carrito + Pedidos + Pagos PostgreSQL (relacional, ACID) El checkout cruza las tres entidades y exige transacción fuerte

La decisión más delicada es la consistencia entre pedido y pago. Como viven en el mismo monolito sobre la misma BD relacional, confirmar el pedido y registrar el pago ocurre en una transacción ACID local: o se hace todo o nada. Esto evita las sagas distribuidas, que solo introduciríamos si más adelante extrajéramos Pagos. La relación con Recomendaciones, en cambio, es consistencia eventual: tras confirmar el pedido se publica un evento y Recomendaciones se actualiza con un pequeño retardo, lo cual es perfectamente aceptable para datos sugeridos.

  1. Comunicación entre componentes

Combinamos estilos de comunicación según la naturaleza de cada interacción:

  • Síncrona (REST/HTTP) a través del gateway para las peticiones del cliente: navegar catálogo, ver carrito, hacer checkout. El usuario espera respuesta inmediata.
  • Asíncrona por eventos para integraciones internas que toleran retardo: PedidoConfirmado dispara la actualización de Recomendaciones y, en el futuro, de Facturación.
  • Anti-Corruption Layer en el servicio de Catálogo si hubiera que integrarse con un PIM (Product Information Management) heredado con un modelo de datos antiguo.
# Contrato del evento de dominio publicado al confirmar un pedido
evento: PedidoConfirmado
version: 1
payload:
  idPedido: "uuid"
  idCliente: "uuid"
  lineas:
    - idProducto: "uuid"
      cantidad: 2
  total: 149.90
  moneda: "EUR"
  fecha: "2026-06-30T10:15:00Z"

Este contrato de evento es la frontera pública entre el monolito y los consumidores (Recomendaciones hoy, Facturación mañana). Definirlo de forma explícita y versionada (version: 1) es esencial: los consumidores dependen de su forma, así que un cambio incompatible exigiría una version: 2. El evento lleva solo lo necesario y no incluye datos personales sensibles más allá de identificadores, lo que además ayuda a respetar la minimización de datos.

  1. Despliegue

El despliegue refleja la arquitectura mixta y el presupuesto contenido:

  • Contenedores (Docker) orquestados con Kubernetes, pero con pocas piezas: monolito, catálogo, recomendaciones, gateway y broker. No multiplicamos servicios sin necesidad.
  • Escalado horizontal independiente: Catálogo se configura con autoescalado agresivo (muchas réplicas en campaña); el monolito y los demás, con un escalado más moderado.
  • Despliegue independiente por squad: cada contenedor tiene su propio pipeline, de modo que el squad de Catálogo despliega sin coordinarse con el de Pedidos. Esto satisface el atributo de autonomía.
  • Estrategia de despliegue progresivo (canary o blue-green) para reducir el riesgo en cada release, con posibilidad de revertir.
# Esbozo de autoescalado del servicio de Catálogo (HPA de Kubernetes)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: catalogo-hpa
spec:
  scaleTargetRef:
    kind: Deployment
    name: catalogo
  minReplicas: 3
  maxReplicas: 60          # holgura para el pico x50 de campaña
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 65

Este manifiesto materializa el requisito de escalabilidad granular: el catálogo puede pasar de 3 a 60 réplicas automáticamente cuando la CPU supera el 65% de uso, absorbiendo el pico de campaña, mientras el resto del sistema mantiene su capacidad habitual. Es exactamente el beneficio que justificaba extraer Catálogo como servicio aparte.

  1. Observabilidad

Un sistema con piezas distribuidas y eventos asíncronos es opaco sin observabilidad. Implementamos los tres pilares:

  • Logs estructurados (JSON) centralizados, con un traceId común en todas las piezas.
  • Métricas (Prometheus/Grafana): latencia p95 por servicio, tasa de errores, profundidad de las colas del broker, réplicas activas.
  • Trazas distribuidas (OpenTelemetry): seguir una petición de checkout a través del gateway, el monolito y el broker, viendo dónde se va el tiempo.

La observabilidad no es un lujo: es la condición previa para evolucionar con seguridad. Sin métricas de latencia del catálogo, no sabríamos si el autoescalado funciona; sin trazas, depurar el flujo de eventos de Recomendaciones sería adivinar. Además, las métricas alimentan fitness functions continuas: una alerta si el p95 de checkout supera 300 ms es una función de aptitud que vigila la salud arquitectónica en producción.

  1. Decisiones registradas (ADR) y evolución

Cerramos el diseño documentando las decisiones clave como ADR, tal y como vimos en la lección de gobernanza:

  • ADR-001: Empezar con monolito modular y extraer servicios solo por dolor (escalado/disponibilidad). Consecuencia: bajo coste inicial; aceptamos refactorizar fronteras más tarde.
  • ADR-002: Extraer Catálogo como servicio independiente. Consecuencia: escalado granular; coste de una BD y un pipeline propios.
  • ADR-003: Comunicación asíncrona por eventos hacia Recomendaciones. Consecuencia: desacople y disponibilidad; consistencia eventual e idempotencia obligatoria.
  • ADR-004: Mantener Carrito, Pedidos y Pagos juntos con transacción ACID local. Consecuencia: consistencia fuerte sin sagas; reevaluar si Pagos necesita escalar aparte.

Y protegemos la arquitectura con fitness functions: tests de ArchUnit que prohíben ciclos entre los módulos del monolito y que impiden que el dominio dependa de la infraestructura, más una fitness continua de latencia en producción. Así, la arquitectura está documentada (ADR) y vigilada (fitness functions): puede evolucionar sin degradarse. Cuando un módulo del monolito empiece a doler, el Strangler Facade ya está en su sitio para extraerlo de forma incremental.

  1. Errores Comunes y Consejos

  • Empezar por la solución y no por los atributos de calidad. Diseñar "con microservicios" antes de saber qué hay que escalar es ponerse la respuesta antes que la pregunta.
  • Extraer servicios por moda. Cada servicio extraído cuesta operación, observabilidad y consistencia. Extrae solo donde el atributo de calidad lo justifique (Catálogo sí, Pagos todavía no).
  • Olvidar la consistencia al separar. En el momento en que partes una transacción entre servicios, entras en sagas y consistencia eventual. Tenlo claro antes de cortar.
  • Diseñar sin observabilidad. Un sistema mixto sin trazas ni métricas es imposible de evolucionar con seguridad.
  • No documentar las decisiones. Sin ADR, dentro de un año nadie recordará por qué Pagos está en el monolito y alguien lo "arreglará" creando un lío.
  • Consejo: revisa que cada decisión del diseño se pueda trazar hasta un requisito o atributo de calidad concreto. Si no puedes, probablemente sobra.

  1. Ejercicios

Ejercicio 1. El negocio añade un requisito: "el envío de emails transaccionales (confirmación de pedido) no debe ralentizar el checkout y debe poder reintentarse si el proveedor de email falla". ¿Cómo lo integrarías en la arquitectura propuesta?

Ejercicio 2. Tras seis meses, las métricas muestran que Pagos sufre picos propios y el equipo quiere desplegarlo aparte. Describe, con lo aprendido, cómo lo extraerías del monolito y qué problema nuevo de consistencia aparece.

Ejercicio 3. Justifica por qué Catálogo usa un almacén orientado a búsqueda y lecturas, mientras que Pedidos usa un relacional ACID. Relaciona cada elección con un atributo de calidad.

Soluciones

Solución 1. Mediante comunicación asíncrona por eventos: el checkout publica PedidoConfirmado (ya existe) y un consumidor de notificaciones envía el email de forma diferida. Así el checkout no espera al email; si el proveedor falla, el consumidor reintenta desde la cola. Conviene idempotencia para no enviar el correo dos veces si el evento se reentrega.

Solución 2. Aplicando Branch by Abstraction dentro del monolito (interfaz ServicioPagos), luego construyendo el microservicio de Pagos con su propia BD y conmutando con feature flags vía el gateway (Strangler). El problema nuevo: la confirmación de pedido y el registro de pago dejan de compartir transacción ACID; aparece la necesidad de una saga con compensación (p. ej. cancelar el pedido si el pago falla) y consistencia eventual entre ambos.

Solución 3. Catálogo prioriza rendimiento y escalabilidad de lectura (búsqueda rápida sobre decenas de miles de referencias bajo picos x50), de ahí un almacén optimizado para búsqueda y réplicas. Pedidos prioriza consistencia: el checkout cruza carrito, pedido y pago en una operación que debe ser todo-o-nada, lo que exige transacciones ACID de un relacional.

  1. Conclusión del curso

Con este estudio de caso cerramos el curso de Arquitectura de Aplicaciones. Hemos visto cómo un buen diseño no nace de elegir la tecnología de moda, sino de un razonamiento disciplinado: traducir requisitos de negocio en atributos de calidad medibles, elegir el estilo que mejor los equilibra —en MercadoFiatc, un monolito modular que evoluciona extrayendo solo lo que lo justifica—, modelar los datos según las necesidades de consistencia, combinar comunicación síncrona y asíncrona, desplegar con escalado granular donde importa, y sostenerlo todo con observabilidad. Y, sobre todo, hemos cerrado el círculo del módulo final: documentar las decisiones con ADR, protegerlas con fitness functions y dejar preparado el Strangler Facade para seguir evolucionando de forma incremental y guiada.

A lo largo del curso has recorrido el camino completo: qué es la arquitectura, los estilos monolíticos y distribuidos, las capas y la arquitectura hexagonal, la gestión de datos y la comunicación, el despliegue, y finalmente la evolución y la gobernanza. La lección de fondo es siempre la misma: en arquitectura no hay soluciones perfectas, solo compromisos bien razonados. Tu trabajo como arquitecto no es eliminar los compromisos, sino elegirlos conscientemente, justificarlos y dejar el sistema preparado para cambiar cuando los compromisos de hoy dejen de servir. Enhorabuena por completar el curso.

Curso de Arquitectura de Aplicaciones

Módulo 1: Fundamentos de la Arquitectura de Aplicaciones

Módulo 2: Principios y Tácticas de Diseño

Módulo 3: Estilos y Patrones Arquitectónicos

Módulo 4: Arquitecturas Distribuidas y Microservicios

Módulo 5: Arquitecturas Dirigidas por Eventos y Mensajería

Módulo 6: Diseño Dirigido por el Dominio (DDD)

Módulo 7: Datos y Persistencia

Módulo 8: Arquitectura en la Nube y Despliegue

Módulo 9: Calidad, Seguridad y Observabilidad

Módulo 10: Evolución, Gobernanza y Casos Prácticos

© Copyright 2026. Todos los derechos reservados