La decisión más difícil al diseñar una arquitectura de microservicios no es la tecnología, sino dónde trazar las fronteras: qué entra en cada servicio y qué queda fuera. Una mala descomposición provoca servicios acoplados que hay que desplegar juntos, esquemas de datos compartidos y cambios que se propagan en cascada. Una buena descomposición produce servicios cohesivos, autónomos y fáciles de evolucionar.

En esta lección estudiaremos las dos estrategias principales de descomposición (por capacidad de negocio y por subdominio), introduciremos el concepto de bounded context del Diseño Guiado por el Dominio (DDD) y aprenderemos a calibrar el tamaño y la granularidad adecuados de un servicio.

Contenido

  1. El problema de las fronteras
  2. Estrategia 1: descomposición por capacidad de negocio
  3. Estrategia 2: descomposición por subdominio (DDD)
  4. Bounded Contexts y lenguaje ubicuo
  5. Granularidad y tamaño adecuado
  6. Acoplamiento, cohesión y el mapa de contextos
  7. Errores comunes y consejos
  8. Ejercicios
  9. Conclusión

  1. El problema de las fronteras

Una frontera mal puesta tiene un coste enorme: corregirla implica mover datos, reescribir APIs y coordinar varios equipos. El objetivo de una buena frontera es maximizar la cohesión dentro del servicio (las cosas que cambian juntas están juntas) y minimizar el acoplamiento entre servicios (cambiar uno no obliga a cambiar otros).

Propiedad Qué buscamos
Cohesión Alta: lo que cambia junto, vive junto.
Acoplamiento Bajo: los servicios dependen poco unos de otros.
Autonomía Alta: cada servicio se despliega y opera solo.

La regla de oro: descompón por dominio de negocio, no por capa técnica. Servicios como "servicio de base de datos", "servicio de validaciones" o "servicio de utilidades" son un antipatrón, porque ningún cambio de negocio se resuelve tocando un solo servicio.

  1. Estrategia 1: descomposición por capacidad de negocio

Una capacidad de negocio es algo que la organización hace para generar valor, independientemente de cómo lo implemente. Se identifican analizando qué hace la empresa, no qué tablas tiene.

En una aseguradora, capacidades típicas serían:

  • Gestión de clientes
  • Contratación de pólizas
  • Tramitación de siniestros
  • Facturación y cobros
  • Reaseguro
# Cada capacidad de negocio se convierte en un candidato a servicio
capacidades:
  contratacion_polizas:
    acciones: [crear_poliza, renovar_poliza, anular_poliza]
    eventos_publicados: [PolizaCreada, PolizaRenovada, PolizaAnulada]
  tramitacion_siniestros:
    acciones: [abrir_siniestro, peritar, indemnizar]
    eventos_publicados: [SiniestroAbierto, SiniestroIndemnizado]

Cada capacidad agrupa las acciones y los eventos que le pertenecen. Esta estrategia es estable, porque las capacidades de negocio cambian mucho menos a menudo que la tecnología.

  1. Estrategia 2: descomposición por subdominio (DDD)

El Diseño Guiado por el Dominio descompone el dominio total en subdominios, que clasifica en tres tipos:

Tipo de subdominio Definición Estrategia recomendada
Núcleo (core) Lo que diferencia a la empresa; su ventaja competitiva. Invertir el mejor esfuerzo; desarrollo propio cuidado.
De soporte (supporting) Necesario pero no diferenciador. Desarrollo más sencillo, posible externalización parcial.
Genérico (generic) Problema común ya resuelto en el mercado. Comprar o usar solución estándar.

Para una aseguradora, el cálculo actuarial de primas es probablemente un subdominio núcleo; la gestión documental es de soporte; y el envío de correos electrónicos es genérico (se usa un proveedor externo).

Esta clasificación guía las inversiones: no tiene sentido construir desde cero un subdominio genérico cuando existen soluciones maduras.

  1. Bounded Contexts y lenguaje ubicuo

Un bounded context (contexto delimitado) es una frontera explícita dentro de la cual un modelo del dominio y su vocabulario tienen un significado preciso y único. La idea central es que la misma palabra puede significar cosas distintas en contextos distintos.

Considera el término "Cliente":

  • En Contratación, un cliente es un tomador con capacidad de contratar y un perfil de riesgo.
  • En Facturación, un cliente es un deudor con una cuenta y unos recibos.
  • En Siniestros, un cliente es un perjudicado o beneficiario.

Forzar un único modelo de "Cliente" para los tres contextos produce una clase gigantesca con decenas de campos que nadie entiende del todo. La solución de DDD es que cada bounded context tenga su propio modelo de Cliente, adaptado a sus necesidades.

// Mismo concepto, dos modelos según el bounded context.

// Contexto Contratación: nos importa el riesgo
package com.fiatc.contratacion;
public class Cliente {
    private String id;
    private PerfilRiesgo perfilRiesgo;
    private List<Poliza> polizasVigentes;
}

// Contexto Facturación: nos importan los cobros
package com.fiatc.facturacion;
public class Cliente {
    private String id;            // mismo identificador para correlacionar
    private FormaPago formaPago;
    private List<Recibo> recibosPendientes;
}

El id actúa como nexo entre contextos, pero cada modelo solo contiene lo que su dominio necesita. El lenguaje ubicuo es el vocabulario común que comparten desarrolladores y expertos de negocio dentro de un contexto, y que se refleja directamente en el código.

graph LR
    subgraph "Contexto Contratación"
        C1[Cliente: tomador]
    end
    subgraph "Contexto Facturación"
        C2[Cliente: deudor]
    end
    subgraph "Contexto Siniestros"
        C3[Cliente: beneficiario]
    end
    C1 -. mismo id .- C2
    C2 -. mismo id .- C3

Cada bounded context es un candidato natural a microservicio. Esta es la regla más fiable para trazar fronteras.

  1. Granularidad y tamaño adecuado

¿Cómo de grande debe ser un servicio? No hay una métrica mágica de líneas de código. Mejores indicadores:

  • Cohesión funcional: un servicio debe poder describirse con una frase de negocio.
  • Transaccionalidad: lo que necesita estar en una misma transacción ACID debería vivir en el mismo servicio.
  • Ritmo de cambio: lo que cambia junto debe estar junto.
  • Autonomía del equipo: un servicio cabe en la cabeza de un equipo pequeño.
Síntoma Diagnóstico Acción
Muchas llamadas entre dos servicios para cada operación Demasiado fragmentado Fusionar
Para un cambio de negocio hay que tocar 5 servicios Fronteras mal puestas Rediseñar fronteras
Un servicio con docenas de responsabilidades dispares Demasiado grande Dividir
Necesitas transacciones distribuidas constantemente División incorrecta Reagrupar por consistencia

El consejo práctico: empieza con servicios más grandes de lo que crees necesario y divídelos cuando aparezca dolor real. Es mucho más fácil dividir un servicio que fusionar dos.

  1. Acoplamiento, cohesión y el mapa de contextos

DDD propone documentar cómo se relacionan los contextos mediante un mapa de contextos. Algunos patrones de relación:

  • Cliente/Proveedor: un contexto consume la API de otro; el proveedor debe respetar las necesidades del cliente.
  • Conformista: el consumidor se adapta sin más al modelo del proveedor.
  • Capa anticorrupción (ACL): el consumidor traduce el modelo ajeno al suyo propio para no contaminarse.
// Capa anticorrupción: traduce el modelo externo al modelo interno
public class ClienteAcl {
    public Cliente traducir(ClienteExternoDTO dto) {
        // No dejamos que el modelo externo "se cuele" en nuestro dominio
        Cliente cliente = new Cliente();
        cliente.setId(dto.getCodigo());           // mapeo de nombres
        cliente.setPerfilRiesgo(calcular(dto));    // adaptación de semántica
        return cliente;
    }
}

La capa anticorrupción es valiosísima al integrar sistemas heredados: aísla tu modelo limpio de las rarezas del sistema externo.

Errores Comunes y Consejos

  • Descomponer por capas técnicas (datos, validación, lógica): cualquier cambio de negocio toca todos los servicios. Descompón por dominio.
  • Un único modelo canónico para toda la empresa: produce modelos gigantes e inmanejables. Adopta bounded contexts.
  • Servicios demasiado pequeños desde el principio: empieza grande y divide ante el dolor real.
  • Ignorar a los expertos de negocio: las fronteras correctas surgen de conversaciones con quienes conocen el dominio (técnicas como el Event Storming ayudan).
  • Compartir tablas entre contextos: rompe la frontera. Usa APIs o eventos.

Ejercicios

  1. Explica con tus palabras qué es un bounded context y por qué la misma palabra ("Cuenta", "Producto"...) puede necesitar modelos distintos en contextos distintos.
  2. Clasifica los siguientes subdominios de un banco en núcleo, de soporte o genérico, y justifica: (a) motor de scoring crediticio, (b) gestión de plantillas de documentos, (c) envío de SMS.
  3. Te encuentras dos servicios, "Pedidos" y "Líneas de pedido", que se llaman mutuamente decenas de veces por operación y comparten transacciones. ¿Qué diagnóstico haces y qué acción tomas?

Soluciones

  1. Un bounded context es una frontera dentro de la cual un modelo y su vocabulario tienen un significado único y coherente. La misma palabra necesita modelos distintos porque cada contexto se interesa por atributos y comportamientos diferentes: "Producto" en catálogo lleva descripción e imágenes, mientras que en almacén lleva ubicación y stock. Unificarlos crea un modelo sobrecargado.

  2. (a) Núcleo: el scoring diferencia al banco y es su ventaja competitiva; desarrollo propio cuidado. (b) Soporte: necesario pero no diferenciador; desarrollo sencillo. (c) Genérico: problema resuelto; se contrata un proveedor de SMS.

  3. Diagnóstico: están demasiado fragmentados; la fragmentación cruza una frontera transaccional. Acción: fusionarlos en un único servicio "Pedidos" que contenga las líneas como parte de su agregado, eliminando las llamadas de red y permitiendo transacciones ACID locales.

Conclusión

Hemos visto que la clave de una buena arquitectura de microservicios está en trazar fronteras por dominio de negocio, apoyándonos en las capacidades de negocio y, sobre todo, en los bounded contexts del DDD. La granularidad correcta busca alta cohesión y bajo acoplamiento, y conviene empezar con servicios grandes y dividir ante el dolor real.

Una vez definidos los servicios y sus fronteras, surge la pregunta práctica de cómo se hablan entre sí sin acoplarse en exceso. La siguiente lección, API Gateway, Service Discovery y Comunicación entre Servicios, aborda precisamente los mecanismos de comunicación síncrona y asíncrona, y la infraestructura que los hace posibles.

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