Hoja de trabajo semana 5 - martin-hendricks/MISO-PROYECTO-FINAL-SOLVENTA GitHub Wiki

Hoja de trabajo semana 5

Proyecto Solventa — Aseguradora digital
Elaboración Juan Acevedo, John Guerrero, Mauricio Rodriguez, Martin Romero
Versión 1.0
Atributos priorizados Escalabilidad y Latencia (desempeño)
Insumos Enunciado MISW4501-202614-Proyecto.pdf ·

Consolidado de la semana 5: modelos de arquitectura, diseño detallado con tácticas y patrones, y diseño del experimento de arquitectura.

Índice

  1. Modelos de arquitectura
  2. Diseño detallado de arquitectura
  3. Diseño del experimento de arquitectura

1. Modelos de arquitectura

Diagramas embebidos de las tres vistas actualizadas (funcional, despliegue, información). Si el embebido no se ve bien en tu navegador (los SVG grandes a veces se recortan en la vista de wiki), usa el link "Abrir el SVG completo" debajo de cada uno para verlo en tamaño real con zoom/scroll.


1.1 Modelo de contexto

Proyecto Solventa — Aseguradora digital
ID VC-001
Elaboración Juan Acevedo, John Guerrero, Mauricio Rodriguez, Martin Romero
Versión 1.0
Vista Contexto
Modelo Contexto

Convención

🟩 Sistema a diseñar Solventa
🟨 Canal Cliente web, cliente móvil, API embebida
🟦 Sistema externo Open Finance, Open Data, KYC, pagos, firma, IoT, reaseguro, estándares
👤 Actor Un nodo por rol × canal (evita cruces)

Actores por canal

Canal Actores Uso principal
Cliente web Asesor / Operaciones, Socio, Peritos, Cliente (escritorio) Gestión completa y back-office
Cliente móvil Cliente asegurado Autoservicio: siniestro con evidencia, push, biometría, geo
API embebida Socio de distribución Cotización / emisión en canal del tercero

Modelo de contexto — Solventa


1.2 Vista funcional — Modelo de componentes

Proyecto Solventa — Aseguradora digital
ID VC-002
Elaboración Juan Acevedo, John Guerrero, Mauricio Rodriguez, Martin Romero
Versión 1.0
Vista Funcional
Modelo Componentes

Incluye :Consentimiento como precondición de la salida a Open Finance —conectado a :AdaptadorOF—, el Dominio · Transversal (Documentos, Analítica, Notificaciones) separado de Venta y Operación, interfaces nombradas (ICotizacion, IPerfilamiento, IPublicacion, ISuscripcion, etc.) y los almacenes replicados de :MsPolizas y :MsSiniestros (Principal), que hacen visible sobre el modelo C&C la política de redundancia que se razona en §1.4.3.

Modelo de componentes — Solventa

Abrir el SVG completo: files/componentes_semana5.svg

1.2.1 Tácticas de arquitectura utilizadas para favorecer la LATENCIA

Táctica (nombre del catálogo) Familia Componente del diagrama Escenario
Múltiples copias de datos II :CacheOF, :CacheOD delante de :AdaptadorOF / :AdaptadorOD EC-LAT-09 — p95 ≤ 250 ms resolviendo con valor de respaldo
Limitar la respuesta a los eventos I :MsPolizas confirma y publica en :BusEventos; firma y notificación salen del camino crítico. :ColaPagos entre :MsPagos y el flujo asíncrono EC-LAT-05 / EC-LAT-06 — p95 ≤ 1,5 s · p99 ≤ 3 s
Introducción de concurrencia II Nota consulta paralelo sobre el fan-out de :MsPerfilamiento hacia :AdaptadorOF y :AdaptadorOD EC-LAT-03 / EC-LAT-04 — p95 ≤ 400 ms · p99 ≤ 800 ms

La decisión de invocar los dos adaptadores en paralelo se declara aquí, sobre el conector; la asignación de ese fan-out a nodos de ejecución y la aritmética que la obliga se documentan en §1.3.1.

1.2.2 Tácticas de arquitectura utilizadas para favorecer la ESCALABILIDAD

Táctica (nombre del catálogo) Familia Componente del diagrama Escenario
Introducción de concurrencia + contrapresión II :AdaptadorTelemetria → :TopicoTelemetria → :MotorParametrico: el tópico desacopla al productor del consumidor y absorbe el pico EC-ESC-03 — ≥ 1.000.000 eventos en 10 min, con procesamiento exactamente una vez

Lo que este modelo hace evidente es el conector asíncrono y la dirección de sus interfaces (IPublicacion / ISuscripcion). El grupo de consumidores no está dibujado aquí porque es una decisión de asignación: vive en §1.3.2, junto a las réplicas y los nodos de ejecución.

Junto con la introducción de concurrencia de §1.2.1, son las dos tácticas que se hacen evidentes en dos modelos a la vez: el conector en el modelo C&C, su asignación en el de despliegue.

1.2.3 Tácticas de arquitectura utilizadas para favorecer la MODIFICABILIDAD y otros atributos

Los patrones de §2.7 aterrizan mayoritariamente tácticas de modificabilidad, no de desempeño. Se documentan sobre este modelo para que la trazabilidad táctica → patrón quede completa. No son los atributos priorizados, pero sostienen a los que sí lo son — el bajo acoplamiento, en particular, es precondición del escalamiento selectivo. Se suman aquí las dos tácticas de disponibilidad que el diagrama hace explícitas con componentes propios: las dos políticas de redundancia sobre los almacenes de pólizas y de siniestros.

Táctica (nombre del catálogo) Atributo Componente del diagrama Escenario
Reducción del acoplamiento Modificabilidad Interfaces provided/required entre componentes; :BusEventos como intermediario orientado a mensajes; capa :Adaptador* EC-MOD-05 · EC-INT-03 · EC-INT-04
Mantener alta cohesión Modificabilidad Submódulos de Dominio · Venta y Dominio · Operación; cada motor separado de su orquestador EC-MOD-01 · EC-MOD-03 · EC-MOD-04
Utilización de un API Gateway Disponibilidad y seguridad :ApiGateway con :APISocios, :BFFWeb, :BFFMovil, :ApiTelemetria EC-INT-04 · EC-SEG-07
Redundancia activa Disponibilidad y latencia :MsPolizas —IDB→ :DBPolizas y —Replica→ :DBPolizas (Replica); la réplica está en el camino de lectura EC-LAT-10 — p95 ≤ 150 ms · RPO ≤ 30 s
Redundancia pasiva + sincronización de estado Disponibilidad :MsSiniestros (Principal) —IDB→ :DBSiniestros —Sincronización→ :Sincronizador —Replica→ :DBSiniestros (Replica); la réplica no sirve tráfico EC-DISP-06 / EC-DISP-07 — RTO ≤ 10 min

Las dos tácticas de redundancia se catalogan sobre este modelo —y no sobre el de despliegue— porque :Sincronizador y las réplicas son componentes con conectores propios, no instancias de un mismo nodo. El razonamiento de por qué son dos políticas distintas, y no una sola, está en §1.4.3. El detector de fallas (Monitor, heartbeat / ping-echo) que promueve la réplica pasiva no aparece en este diagrama: se documenta en ese mismo apartado.

1.2.4 Razonamiento sobre las principales decisiones de arquitectura tomadas en este modelo

Por qué :MsCotización y :MsPerfilamiento son componentes separados. No es modularidad estética: sus curvas de carga no coinciden. :MsCotización escala con la campaña de un socio (EC-ESC-01, pico inducido y previsible); :MsPerfilamiento escala con el cierre de mes de los bancos aliados (EC-LAT-04, pico de originación). Escalarlos juntos obliga a dimensionar por el máximo de ambos. Esta es la justificación de fondo del estilo de microservicios en este caso.

Respuesta a la pregunta 3 del enunciado (¿cómo se protege el presupuesto de latencia de la cotización cuando depende de Open Finance?): no con el :ApiGateway —que añade un salto—, sino porque :CacheOF ya tiene el perfil y la llamada a :AdaptadorOF es una actualización oportunista, no una dependencia bloqueante. EC-LAT-08 corta a 700 ms y :MsCotización resuelve con el respaldo.

Por qué las réplicas de datos son componentes de este modelo y no solo del de despliegue. :DBPolizas (Replica) y :DBSiniestros (Replica) no son la misma decisión repetida en dos servicios: son dos políticas de redundancia distintas, y lo que las separa es el conector, no el nodo. En pólizas se aplica redundancia activa: la réplica cuelga directamente de :DBPolizas y queda dentro del camino de lectura, atendiendo tráfico en producción. En siniestros se aplica redundancia pasiva: aparece un componente intermedio, :Sincronizador, precisamente porque la réplica no debe servir tráfico y solo se promueve ante la caída de la zona. Un modelo de despliegue mostraría en ambos casos dos instancias en zonas distintas y perdería esa diferencia, que es justo la decisión relevante.

Por qué activa en pólizas y pasiva en siniestros. El criterio no es la criticidad del dato sino la naturaleza del problema. En pólizas el problema es de volumen de lectura —la consulta de cobertura vigente llega desde web y desde móvil sobre el mismo dato—, así que una réplica ociosa sería capacidad pagada y desaprovechada: se pone a trabajar y se acepta el desfase acotado del RPO. En siniestros el problema es de continuidad, no de volumen: poner la réplica a servir lecturas introduciría staleness sobre un dato que el cliente lee como el estado vigente de su reclamación, así que se mantiene fuera del tráfico. Los mecanismos, las medidas y el disparador de la promoción están en §1.4.3.

Por qué el bajo acoplamiento no es un tema secundario aquí. Solo se puede replicar de forma independiente aquello que no arrastra a sus vecinos. Si :MsCotización dependiera de la implementación de sus colaboradores, escalarla obligaría a escalarlos con ella y desaparecería la ventaja de tener curvas de carga separadas. Es decir: la táctica de modificabilidad es la que hace posible la de escalabilidad.


1.3 Vista de despliegue — AWS

Proyecto Solventa — Aseguradora digital
ID VC-003
Elaboración Juan Acevedo, John Guerrero, Mauricio Rodriguez, Martin Romero
Versión 1.0
Vista Asignación / Despliegue
Modelo Despliegue

VPC con subred pública (ALB, WAF, CloudFront) y subredes privadas multi-AZ (EKS con grupos de escalado independientes, RDS PostgreSQL Multi-AZ, ElastiCache Redis, MSK/Kafka), más KMS y Secrets Manager para gestión de credenciales.

Modelo de despliegue — Solventa (AWS)

Abrir el SVG completo: files/DiagramaDespliegueSolventa.svg

1.3.1 Tácticas de arquitectura utilizadas para favorecer la LATENCIA

Táctica (nombre del catálogo) Familia Componente del diagrama Escenario
Introducción de concurrencia II Fan-out paralelo de :MsPerfilamiento hacia :AdaptadorOF y :AdaptadorOD EC-LAT-03 / EC-LAT-04 — p95 ≤ 400 ms · p99 ≤ 800 ms

1.3.2 Tácticas de arquitectura utilizadas para favorecer la ESCALABILIDAD

Táctica (nombre del catálogo) Familia Componente del diagrama Escenario
Múltiples copias de computación II Réplicas de :MsCotización + :MotorRaiting como grupo, separadas de :MsPerfilamiento + :MotorRiesgo EC-ESC-01 — 500 → 50.000 cot/min sostenidas 30 min
Incrementar los recursos de computación II Nodos de :MotorRaiting / :MotorRiesgo (cómputo intensivo, poco estado) EC-ESC-02 — capacidad ampliada ≤ 60 s
Introducción de concurrencia + contrapresión II :AdaptadorTelemetria → :TopicoTelemetria → :MotorParametrico con grupo de consumidores EC-ESC-03 — ≥ 1.000.000 eventos en 10 min, con procesamiento exactamente una vez

Las dos primeras son decisiones de la familia de asignación: su evidencia se documenta en este modelo de despliegue, no en el de componentes.

1.3.3 Tácticas de arquitectura utilizadas para favorecer la DISPONIBILIDAD

Táctica (nombre del catálogo) Familia Componente del diagrama Escenario
Mantener múltiples copias de datos — redundancia activa Detección/recuperación de fallas :DBPolizas → :DBPolizas (Replica), réplica de lectura en AZ-b que atiende tráfico en producción EC-LAT-10 — p95 ≤ 150 ms · RPO ≤ 30 s
Mantener múltiples copias de datos — redundancia pasiva Detección/recuperación de fallas :DBSiniestros → :Sincronizador → :DBSiniestros (Replica), standby Multi-AZ en AZ-b que no sirve tráfico EC-DISP-06 / EC-DISP-07 — RTO ≤ 10 min ante falla zonal
Monitor (heartbeat / ping-echo) Detección de fallas :Monitor vigilando :MsPolizas, :MsSiniestros y :Sincronizador; dispara la promoción de la réplica pasiva EC-DISP-06
Multi-AZ activo-activo (cómputo) Redundancia EKS Node Group replicado en AZ-a y AZ-b para los grupos de escalado A y B EC-DISP-06 — RTO ≤ 10 min ante falla zonal

El detalle de por qué pólizas usa redundancia activa y siniestros pasiva —incluyendo la tabla comparativa completa y el rol del :Sincronizador— está desarrollado en §1.4.3, porque es una decisión sobre el dato, no sobre el nodo de cómputo que lo aloja.

1.3.4 Razonamiento sobre las principales decisiones de arquitectura tomadas en este modelo

Aritmética que justifica la concurrencia. EC-LAT-07 fija ≤ 120 ms por dependencia externa y EC-LAT-03 fija 400 ms para todo el perfilamiento. Invocar :AdaptadorOF y :AdaptadorOD en serie consume 240 ms de los 400; en paralelo, 120 ms. El fan-out paralelo es, por tanto, condición necesaria para cumplir el escenario con los proveedores sanos.

Corrección tras HA-01 (18/09/2026). Esta aritmética suponía que EC-LAT-07 se cumple, y el experimento demostró que no se cumple frente a un proveedor degradado: el p95 del adaptador con proveedor lento es de 495,6 ms y el 99,78 % de sus llamadas supera los 120 ms (informe detallado). El paralelo sigue siendo mejor que el serie, pero ya no basta como justificación: con un proveedor degradado el fan-out cuesta hasta el timeout duro de 700 ms, que por sí solo excede los 400 ms de EC-LAT-03.

HA-01 validó el desacople oportunista sólo sobre el camino de cotización (:MsCotización → :CacheOF → :AdaptadorOF). El camino de perfilamiento comparte :AdaptadorOF y no se ejercitó: EC-LAT-03 y EC-LAT-04 quedan sin evidencia frente a dependencia degradada, y su cumplimiento depende de que :CacheOD/:CacheOF apliquen allí la misma táctica de actualización oportunista, lo que no está medido. Es candidato a experimento propio.

Cómo se combinan los dos escalamientos. El horizontal es la decisión por defecto, porque aporta elasticidad y tolerancia a la falla de una zona. El vertical se emplea sobre los motores de cálculo para ganar los primeros segundos de la rampa, donde el aprovisionamiento horizontal aún no ha terminado.

Por qué la disponibilidad no se resuelve con una sola política de redundancia. El diagrama de despliegue por sí solo mostraría dos instancias en zonas distintas para pólizas y para siniestros, y esa vista perdería la decisión relevante: cuál de las dos réplicas sirve tráfico. En pólizas el problema es de volumen de lectura (web y móvil consultando la misma cobertura vigente), así que la réplica se pone a trabajar y se acepta el desfase acotado del RPO — es redundancia activa. En siniestros el problema es de continuidad, no de volumen: dejar que la réplica sirva lecturas introduciría staleness sobre un dato que el cliente interpreta como el estado vigente de su reclamación, así que se mantiene fuera del tráfico y solo se promueve cuando el :Monitor detecta la caída de la zona — es redundancia pasiva. El :Sincronizador es el componente que hace esa diferencia visible en el despliegue: sin él, ambas réplicas se verían idénticas.

Qué no resuelve esta redundancia. La disponibilidad ante falla de zona (este modelo) y la latencia de consulta del estado de siniestro (EC-LAT-11, resuelta con CQRS en el experimento HA-08 de §3) son dos problemas distintos que comparten componente pero no solución: la réplica pasiva de :DBSiniestros no está diseñada para servir el p95 ≤ 150 ms que exige la consulta de estado, solo para sobrevivir a la caída de la zona.


1.4 Vista de información

1.4.1 Modelo de datos

Proyecto Solventa — Aseguradora digital
ID VC-004
Elaboración Juan Acevedo, John Guerrero, Mauricio Rodriguez, Martin Romero
Versión 1.0
Vista Información / Dominio
Modelo Dominio / Datos (entidad-relación por microservicio)

Convención

Rectángulo (entidad) Entidad del dominio de negocio
+ atributo Campo público / dato de negocio relevante
--> Asociación dirigida entre entidades
"1", "0..*", "1..*" Cardinalidad de la relación
Etiqueta en arista Rol o verbo de la relación (p. ej. otorga, genera)

Formato del diagrama

Lenguaje Diagrama entidad-relación publicado como SVG
Orientación Agrupado por microservicio
Alcance Entidades y relaciones del caso Solventa (cotización → póliza → siniestro / pago)

Modelo entidad-relación por microservicio (ms_identidad, ms_consentimiento, ms_cotizacion, ms_perfilamiento, ms_suscripcion, ms_polizas, ms_siniestros, ms_pagos, ms_parametrico, ms_socios, analitica, notificaciones), con claves foráneas cruzando límites de servicio donde aplica.

Modelo de datos — Solventa

Abrir el SVG completo: files/ModeloDatosSolventa.svg

1.4.2 Flujo de control sobre el modelo de información

Proyecto Solventa — Aseguradora digital
ID VC-007
Elaboración Juan Acevedo, John Guerrero, Mauricio Rodriguez, Martin Romero
Versión 1.0
Vista Información / Dominio
Modelo Flujo de control (secuencia) sobre las estructuras de datos
Alcance Los dos recorridos que mueven el estado de la póliza: cotización con perfilamiento, y emisión con propagación asíncrona. No cubre siniestros, pagos ni telemetría paramétrica.

Convención

actor Origen de la petición fuera del sistema (socio de distribución, canal embebido)
boundary Frontera del sistema: API Gateway / BFF, Adaptador Open Finance y el proveedor externo
control Microservicio que orquesta el recorrido (Cotización & Rating, Emisión & Pólizas)
entity Estructura de datos en caché (Caché de Perfiles, Redis Multi-AZ)
database Almacén transaccional propio del servicio (DB Pólizas, PostgreSQL)
queue Conector asíncrono de transferencia de estado (Event Broker, Apache Kafka)
alt / else Bifurcación del flujo de control
Flecha punteada Retorno de la llamada

Vista de información — Flujo de control

Abrir la imagen completa: out/images/vista_informacion_flujo_control/Solventa_Vista_Informacion_Flujo_Control.png · Fuente PlantUML: images/vista_informacion_flujo_control.puml

Recorrido 1 — Cotización y perfilamiento (pasos 1 a 13). El control entra por el API Gateway / BFF y baja al microservicio de Cotización & Rating, que primero consulta la caché de perfiles. Con acierto de caché (perfil válido < 24 h) el recorrido termina ahí y no hay salida a la red externa. Con fallo o perfil desactualizado se invoca al Adaptador Open Finance contra el proveedor, con timeout duro de 700 ms; si el proveedor responde dentro del presupuesto de ≤ 120 ms por dependencia externa, el perfil se enriquece, y si falla o excede el corte, el adaptador devuelve un perfil estándar por defecto y el flujo continúa. En ambas ramas el perfil calculado se reescribe en caché con TTL de 24 h antes de calcular la prima. Es el mismo comportamiento que fija EC-LAT-09 y que se argumenta en §1.4.4.

Recorrido 2 — Emisión, persistencia y consistencia eventual (pasos 14 a 20). Emisión & Pólizas escribe la póliza en su propio almacén y espera el commit; solo después publica PolizaEmitidaEvent en el broker y responde al socio. Notificación legal, conciliación de recaudo y auditoría regulatoria (SFC) quedan del lado asíncrono, fuera del camino crítico de la respuesta — es la táctica limitar la respuesta a los eventos de §1.2.1 vista desde los datos, y sostiene tanto EC-LAT-05 como la trazabilidad que exige EC-SEG-04.

Estructuras de datos que atraviesan el flujo

Estructura Dónde vive Qué transporta
solicitudDTO Entrada del gateway hacia Cotización & Rating Cliente, ConsentimientoToken, DatosRiesgo
PerfilRiesgo Caché de perfiles (Redis Multi-AZ) Score y segmento; TTL de 24 h
Señales financieras Respuesta del proveedor Open Finance Endeudamiento, capacidad de pago
Perfil estándar por defecto Adaptador Open Finance (rama degradada) Valor de respaldo cuando el tercero no responde a tiempo
OfertaSeguroDTO Retorno de la cotización OfertaID, prima calculada, coberturas, vigencia
ComandoEmisionDTO Entrada de la emisión OfertaID, TokenPagoConfirmado
Poliza DB Pólizas (PostgreSQL) NumeroPoliza, estado EMITIDA, FirmaHash
PolizaEmitidaEvent Tópico del Event Broker Payload transaccional para notificaciones, recaudo y auditoría
PolizaEmitidaDTO Retorno de la emisión NumeroPoliza, estado, HashFirmaLegal

1.4.3 Estrategia de replicación (activa/pasiva)

Cada almacén propio se replica sobre las subredes privadas multi-AZ de §1.3, pero no con la misma política en todos los servicios: la decisión se fija en este modelo.

Estrategia de replicación — MsPolizas (activa) y MsSiniestros (pasiva)

Abrir la imagen completa: out/images/DiagramaRedundanciaPolizasSiniestros/DiagramaRedundanciaPolizasSiniestros.png · Fuente PlantUML: images/DiagramaRedundanciaPolizasSiniestros.puml

Redundancia activa — :MsPolizas Redundancia pasiva — :MsSiniestros
Qué hace la réplica Atiende lecturas en producción todo el tiempo No sirve tráfico; el Sincronizador la mantiene al día
Mecanismo Streaming replication de RDS PostgreSQL hacia una read replica en AZ-b Standby Multi-AZ en AZ-b alimentado por el Sincronizador
Atributo que sostiene Latencia — descarga de lecturas del nodo de escritura Disponibilidad — continuidad ante caída de zona
Escenario EC-LAT-10 — p95 ≤ 150 ms EC-DISP-06 / EC-DISP-07
Medida declarada RPO ≤ 30 s RTO ≤ 10 min
Quién dispara el cambio — (la réplica ya está en el camino de lectura) El Monitor promueve la réplica a principal

Por qué dos políticas de redundancia y no una sola. En pólizas el problema es de volumen de lectura: la consulta de cobertura vigente llega desde web y desde móvil sobre el mismo dato, y mantener una réplica ociosa sería pagar capacidad que hoy alivia al nodo de escritura. Por eso la réplica está en el camino de lectura y se acepta el desfase acotado del RPO. En siniestros el problema no es volumen sino continuidad: poner una réplica a servir lecturas ahí introduciría staleness sobre un dato que el cliente interpreta como estado vigente de su reclamación, así que la réplica se mantiene fuera del tráfico y solo se promueve cuando el Monitor (heartbeat / ping-echo) detecta la caída de la zona.

Qué no resuelve esta réplica. La lectura de baja latencia del estado de siniestro (EC-LAT-11) no se atiende con la réplica de disponibilidad: se atiende con un modelo de lectura separado (CQRS), que es precisamente la hipótesis que valida el experimento de §3 sobre la historia HA-08. Separar los dos problemas —disponibilidad de la zona por un lado, latencia de consulta por el otro— es la decisión de fondo de este modelo: mezclarlos habría llevado a exigirle a una réplica de failover un objetivo de desempeño que no está diseñada para cumplir.

Dónde queda el detector de fallas. Las dos políticas de redundancia sí quedan catalogadas como tácticas sobre el modelo C&C, en §1.2.3, porque las réplicas y el Sincronizador son componentes del diagrama de componentes. El Monitor que emite heartbeat / ping-echo hacia :MsPolizas, :MsSiniestros y el Sincronizador solo aparece en este modelo de replicación: es una táctica de disponibilidad, no de desempeño, y por eso no figura en el catálogo de §2.4 ni de §2.5.

1.4.4 Razonamiento sobre las decisiones de datos

Este modelo no aporta tácticas propias: el catálogo clasifica como Modelo C&C la única táctica que actúa sobre los datos (múltiples copias de datos), de modo que su ficha vive en §1.2.1. Lo que sigue es el razonamiento sobre las decisiones de información que ese reparto implica. La estrategia de replicación entre zonas se desarrolla en el apartado anterior, §1.4.3.

Un almacén por servicio, no un esquema compartido. El estilo de microservicios de §2.3 define cada unidad desplegable con almacén propio; por eso el modelo entidad-relación está agrupado por microservicio (ms_identidad, ms_consentimiento, ms_cotizacion, ms_perfilamiento, ms_suscripcion, ms_polizas, ms_siniestros, ms_pagos, ms_parametrico, ms_socios, analitica, notificaciones) y no como un esquema único. Lo que se paga a cambio está declarado en el mismo estilo: consistencia distribuida. Las claves foráneas que cruzan límites de servicio son la excepción explícita del modelo, no la regla.

Dónde se acepta consistencia eventual y dónde no. Aplica la regla de reparto de §2.3: es síncrono lo que el usuario espera mirando la pantalla (cotizar, perfilar, suscribir, emitir) y asíncrono lo que puede converger después (notificar, analizar, conciliar, telemetría paramétrica). Por eso la información que alimenta a :Analitica, :Notificaciones y :Documentos se propaga por :BusEventos y se lee con consistencia eventual, mientras que la cadena cotización → póliza → siniestro / pago mantiene consistencia inmediata dentro de su propio almacén. El costo declarado del estilo publicador-suscriptor —consistencia eventual e idempotencia— se paga solo de ese lado, y es el mismo requisito de procesamiento exactamente una vez que fija EC-ESC-03.

Copias hacia proveedores externos. Además de la replicación entre zonas (§1.4.3), :CacheOF y :CacheOD conservan una copia local con valor de respaldo del perfil de Open Finance / Open Data: la llamada al adaptador es una actualización oportunista y no una dependencia bloqueante, que es lo que permite resolver EC-LAT-09 sin depender de la disponibilidad del tercero.


1.5 Arquitectura del portal web (MVVM)

Proyecto Solventa — Aseguradora digital
ID VC-005
Elaboración Juan Acevedo, John Guerrero, Mauricio Rodriguez, Martin Romero
Versión 1.0
Vista Desarrollo / capas
Modelo Patrón MVVM del portal web (Angular)
Alcance Solo el canal web (SPA Angular). No cubre el cliente móvil, el BFF ni los microservicios.

Diagrama de componentes del portal web Angular: View (componentes standalone, sin lógica de negocio) → ViewModel (estado observable con signals, expone loading / ready / degraded / error) → Model (dominio puro, casos de uso y puertos, arquitectura hexagonal en el front). Cada uno de los cinco recorridos críticos (cotización, suscripción y emisión, perfilamiento hipotecario, siniestro asistido, ciclo de vida de póliza) es un feature module con lazy loading.

Arquitectura MVVM — Portal web Solventa

Abrir en tamaño completo: files/Diagram-web/solventa-portal-web-mvvm.png · Fuente PlantUML: files/Diagram-web/solventa-portal-web-componentes_1.puml · Documento completo (razonamiento, código de ejemplo, convenciones de carpetas, riesgos): files/Diagram-web/mvvm-portal-web-solventa_1.md


1.6 Arquitectura del cliente móvil (Android)

Proyecto Solventa — Aseguradora digital
ID VC-006
Elaboración Juan Acevedo, John Guerrero, Mauricio Rodriguez, Martin Romero
Versión 1.0
Vista Desarrollo / capas
Modelo Capas del cliente Android (Clean Architecture + MVVM + Repository)

Diagrama de capas en tiempo de ejecución de la app Android (Kotlin / Jetpack). No describe el sistema Solventa completo: cubre el canal móvil (login, póliza, siniestro con evidencia, pagos y renovación) y cómo el cliente se conecta al Mobile BFF y a Room en modo offline-first. El bloque Identidad (derecha) concentra biometría, tokens y el interceptor JWT.

Capas (izquierda → derecha)

Capa Responsabilidad
Presentation (Jetpack + MVVM) MainActivity y fragments (LoginFragment, DetalleFragment, PagoFragment, RenovacionFragment) observan ViewModels (StateFlow / LiveData / UiState). Push vía FCM. El ViewModel invoca casos de uso; no habla con red ni con Room.
Domain Casos de uso (EntrarAlSistema, ReportarSiniestro, ValidarCodigos, ConsultarPagos, RenovarPoliza, SincronizarUsuario) y contratos de repositorio (Póliza / Siniestro / Pago). Sin APIs de Android.
Data (Repository) *RepositoryImpl orquesta remoto vs local: Retrofit y DTO → Mobile BFF; DAOs → Room (SQLite). WorkManager encola evidencia diferida.
Identidad BiometricPrompt (huella / rostro; fallback PIN) desbloquea la sesión en el dispositivo. TokenStore (DataStore / EncryptedPrefs) y AuthInterceptor (OkHttp) inyectan JWT solo en APIs protegidas. Login y refresh no llevan access token; Room y Push no pasan por el interceptor. El JWT se valida en el BFF.

Arquitectura Android Solventa — capas (Clean + MVVM + Repository)

Abrir el SVG completo: images/android-arquitectura-runtime.svg


2. Diseño detallado de arquitectura

2.1 Marco conceptual

Nivel Qué es Qué gobierna
Estilo arquitectónico Decisión de primer nivel y alto grado de abstracción. Establece vocabulario, reglas y lineamientos sobre la topología del modelo y su semántica. Determina qué atributos de calidad quedan intrínsecamente favorecidos o desfavorecidos.
Táctica arquitectónica Técnica que modifica, refina y especializa un estilo en puntos y componentes específicos. Asegura la respuesta y la medida de respuesta estipuladas en un escenario de calidad.
Patrón de diseño Solución conocida a un problema recurrente de estructuración y asignación de responsabilidades entre clases y objetos. Conecta la táctica con el código.
Familia de modelos Qué hace evidente Elementos
Módulo Unidades de implementación (tiempo de desarrollo). Clases, paquetes, capas; relaciones usa a / depende de.
Componente y Conector (C&C) Ejecución en tiempo de corrida. Componentes y conectores — el conector es el elemento determinante para el cumplimiento del atributo de calidad.
Asignación Asignación de software a entidades del mundo real. Despliegue (nodos), concurrencia (procesos/hilos), asignación de trabajo.

Catálogo de desempeño del curso. Desempeño = habilidad de cumplir requerimientos de tiempo; se subdivide en latencia (tiempo entre evento y respuesta) y escalabilidad (incrementar la carga sin perjudicar los tiempos de respuesta).

Familia I — control del acceso a recursos compartidos Familia II — incremento y manejo de recursos disponibles
Manejo de la prioridad de los eventos Introducción de concurrencia
Limitar la respuesta a los eventos Múltiples copias de computación (horizontal)
Incrementar la latencia de los recursos Incrementar los recursos de computación (vertical)
Múltiples copias de datos

La utilización de un API gateway está catalogada por el material como táctica de disponibilidad (ocultar localización e instancias, enmascarar fallas), con uso complementario en seguridad.


2.2 Modelos de referencia

Las decisiones de este documento se sustentan sobre los siguientes modelos:

Modelo Vista Enlace
Modelo de componentes Funcional — Componente y Conector §1.2 Vista funcional — Modelo de componentes
Modelo de despliegue Asignación §1.3 Vista de despliegue — AWS
Modelo de datos Información §1.4 Vista de información

2.3 Estilos arquitectónicos

Estilo Familia Dónde vive Favorece Sacrifica
Microservicios C&C Dominio · Venta y Dominio · Operación como unidades desplegables con almacén propio Escalabilidad selectiva, modificabilidad Latencia de red interna, consistencia distribuida
Llamada-retorno sincrónico (N-niveles) C&C APISocios → :MsCotización → :MotorRaiting Baja latencia y consistencia inmediata en el journey de venta Acoplamiento temporal
Publicador-suscriptor (EDA) C&C :BusEventos → :Analitica, :Notificaciones, :Documentos; :ColaPagos tras :MsPagos; :TopicoTelemetria → :MotorParametrico Escalabilidad: absorbe picos con contrapresión, admite consumidores nuevos sin tocar productores Consistencia eventual, idempotencia
Capas + adaptadores (anticorrupción) Módulo :AdaptadorOF, :AdaptadorOD, :AdaptadorPasarela, :AdaptadorKYC, :AdaptadorTelemetria Modificabilidad e integrabilidad Una indirección más por llamada

Regla de reparto. Es síncrono lo que el usuario espera mirando la pantalla (cotizar, perfilar, suscribir, emitir). Es asíncrono lo que puede converger después (notificar, analizar, conciliar, telemetría paramétrica). Esa frontera es la decisión que más pesa sobre latencia y escalabilidad a la vez.


2.4 Tácticas de LATENCIA

Esta sección queda como índice de trazabilidad: cada táctica se detalla ahora dentro del modelo que la hace evidente, junto al diagrama correspondiente.

Táctica (nombre del catálogo) Familia Modelo donde está presente Detalle
Múltiples copias de datos II Modelo C&C §1.2.1 — Vista funcional
Limitar la respuesta a los eventos I Modelo C&C §1.2.1 — Vista funcional
Introducción de concurrencia II Modelo C&C y de Asignación §1.2.1 — Vista funcional · §1.3.1 — Vista de despliegue

Razonamiento asociado: §1.2.4 — protección del presupuesto de latencia frente a Open Finance — y §1.3.4 — aritmética que justifica la concurrencia.


2.5 Tácticas de ESCALABILIDAD

Esta sección queda como índice de trazabilidad: cada táctica se detalla ahora dentro del modelo que la hace evidente, junto al diagrama correspondiente.

Táctica (nombre del catálogo) Familia Modelo donde está presente Detalle
Múltiples copias de computación II Modelo de Asignación (despliegue) §1.3.2 — Vista de despliegue
Incrementar los recursos de computación II Modelo de Asignación (despliegue) §1.3.2 — Vista de despliegue
Introducción de concurrencia + contrapresión II Modelo C&C y de Asignación §1.2.2 — Vista funcional · §1.3.2 — Vista de despliegue

Razonamiento asociado: §1.2.4 — por qué :MsCotización y :MsPerfilamiento son componentes separados — y §1.3.4 — cómo se combinan los dos escalamientos.


2.6 Tácticas de MODIFICABILIDAD y otras del catálogo

Esta sección queda como índice de trazabilidad: cada táctica se detalla ahora dentro del modelo que la hace evidente, junto al diagrama correspondiente.

Táctica (nombre del catálogo) Atributo Modelo donde está presente Detalle
Reducción del acoplamiento Modificabilidad Modelo de Módulo §1.2.3 — Vista funcional
Mantener alta cohesión Modificabilidad Modelo de Módulo §1.2.3 — Vista funcional
Utilización de un API Gateway Disponibilidad y seguridad Modelo C&C §1.2.3 — Vista funcional
Redundancia activa Disponibilidad y latencia Modelo C&C §1.2.3 — Vista funcional · §1.4.3 — Estrategia de replicación
Redundancia pasiva + sincronización de estado Disponibilidad Modelo C&C §1.2.3 — Vista funcional · §1.4.3 — Estrategia de replicación

Razonamiento asociado: §1.2.4 — por qué el bajo acoplamiento no es un tema secundario aquí, y por qué la redundancia es activa en pólizas y pasiva en siniestros — §1.4.3 — mecanismos, medidas y disparador de la promoción — y §1.4.4 — consecuencias sobre el modelo de información.


2.7 Patrones de diseño que aterrizan las tácticas

Cada patrón se presenta con la táctica que aterriza (descrita en §2.4, §2.5 o §2.6), el componente donde vive, el modelo que lo hace evidente, el escenario que sostiene y la razón por la que se tomó la decisión — no solo qué hace, sino qué alternativa se descartó y qué se aceptó a cambio.


2.7.1 Fachada (GoF)

Táctica que aterriza Utilización de un API Gateway (disponibilidad y seguridad): ocultar la localización y disponibilidad de los microservicios y enmascarar fallas.
Componente del diagrama :ApiGateway con :APISocios, :BFFWeb, :BFFMovil, :ApiTelemetria
Modelo donde está presente Modelo C&C
Escenario EC-INT-04 — evolución compatible de contratos multicanal
ASR HA-31

Por qué esta decisión. Solventa expone su núcleo a cuatro canales con ciclos de vida independientes: una app móvil que queda instalada en el dispositivo del cliente, un portal web, más de treinta socios que integran una vez y no vuelven a tocar el código, y un flujo de telemetría. Sin un punto de entrada único, cada canal quedaría atado a la topología interna del backend: dividir un microservicio o cambiar su dirección obligaría a coordinar el redespliegue de apps ya instaladas y de integraciones de terceros que Solventa no controla. La alternativa —exponer los microservicios directamente— era más simple y más rápida, pero congelaba la estructura interna. Se aceptó un salto de red adicional en el camino crítico a cambio de poder reorganizar el backend sin romper contratos externos, y como beneficio secundario el punto único es donde se concentran el control de acceso y el enmascaramiento de fallas.

Patrón Fachada


2.7.2 BFF — Backend for Frontend (patrón de canal)

Táctica que aterriza Utilización de un API Gateway, especializada por canal. Protege además el presupuesto de latencia al agregar en el borde, aunque la agregación no es una táctica nombrada del catálogo de desempeño.
Componente del diagrama :BFFWeb y :BFFMovil, separados de :APISocios
Modelo donde está presente Modelo C&C
Escenarios EC-INT-04 · EC-LAT-05
ASR HA-31 · HA-05

Por qué esta decisión. Los tres canales no piden lo mismo. La web cubre la gestión completa del negocio; el móvil un subconjunto de tareas rápidas con evidencia, biometría y modo offline; los socios solo cotización y emisión embebidas. Una API única para los tres obligaría a servir el máximo común denominador, y el cliente compensaría la diferencia con varias llamadas encadenadas — un costo que se paga directamente contra el presupuesto de 1,5 s de EC-LAT-05. La alternativa era una sola API y clientes más gordos; se descartó porque traslada al canal un trabajo de composición que el borde hace mejor y más cerca de los datos. Se aceptó mantener tres piezas de borde en vez de una a cambio de que cada canal evolucione a su propio ritmo y de que la agregación ocurra donde no cuesta latencia.

Patrón BFF


2.7.3 Adaptador / Capa anticorrupción (GoF + DIP)

Táctica que aterriza Reducción del acoplamiento (modificabilidad): usar APIs e intermediarios para que el dominio no dependa de la implementación del proveedor.
Componente del diagrama :AdaptadorOF, :AdaptadorOD, :AdaptadorPasarela, :AdaptadorKYC, :AdaptadorTelemetria
Modelo donde está presente Modelo de Módulo
Escenarios EC-MOD-05 · EC-INT-03
ASR HA-28 · HA-30

Por qué esta decisión. El enunciado es explícito en que gran parte del valor del negocio depende de integraciones fuera del control de Solventa, y que la regulación de Finanzas Abiertas sigue madurando. Sin una capa de traducción, el esquema de cada proveedor se filtraría hasta el dominio: los campos de Open Finance aparecerían dentro del motor de riesgo y los de la pasarela dentro de pagos. Ese acoplamiento convierte un cambio de proveedor —o un cambio normativo del proveedor— en un cambio transversal que toca varios componentes. Se aceptó una indirección adicional por llamada a cambio de que la sustitución de un tercero quede contenida en un solo módulo, que es exactamente lo que EC-MOD-05 exige medir.

Patrón Adaptador


2.7.4 Mediador (GoF)

Táctica que aterriza Limitar la respuesta a los eventos (latencia, familia I) e introducción de concurrencia + contrapresión (escalabilidad, familia II).
Componente del diagrama :BusEventos
Modelo donde está presente Modelo C&C
Escenario EC-ESC-03
ASR HA-11

Por qué esta decisión. Un mismo hecho de negocio —una póliza emitida, un siniestro aprobado, un pago aplicado— le interesa a varios consumidores a la vez: analítica, notificaciones, documentos, y mañana fraude o reportes al regulador. Con comunicación punto a punto, cada consumidor nuevo obliga a modificar y redesplegar al productor, y la lista de consumidores solo crece con el negocio. El mediador invierte esa dependencia: el productor publica el hecho y deja de saber quién lo escucha. Se aceptó consistencia eventual —y la obligación de resolver idempotencia y trazabilidad— a cambio de poder sumar consumidores sin tocar productores y de absorber picos con contrapresión en lugar de propagarlos.

Patrón Mediador


2.7.5 Singleton (GoF)

Táctica que aterriza Es consecuencia obligada de Introducción de concurrencia (§2.4) y Múltiples copias de computación (§2.5), ambas de familia II: sin él, esas dos tácticas se anulan entre sí.
Componente del diagrama Pool de conexiones dentro de cada réplica de :MotorRaiting y :MotorRiesgo
Modelo donde está presente Modelo de Asignación (concurrencia y despliegue)
Escenarios EC-LAT-03 · EC-ESC-01
ASR HA-03 · HA-09

Por qué esta decisión. No es una elección estética: es la consecuencia obligada de haber adoptado concurrencia. La táctica de introducción de concurrencia multiplica los hilos dentro de cada réplica, y la de múltiples copias de computación multiplica las réplicas. Si cada hilo abriera su propio pool, las conexiones contra el almacén crecerían como hilos × réplicas — con 4 hilos y 20 réplicas son 80 pools golpeando la misma base. La contienda que se eliminó en el cómputo reaparecería en la persistencia, y las dos tácticas de escalamiento se anularían entre sí. Una única instancia por proceso acota las conexiones y deja que el paralelismo escale sin castigar el almacén.

Patrón Singleton


2.7.6 Experto (GRASP)

Táctica que aterriza Mantener alta cohesión (modificabilidad). Protege además el presupuesto de las tácticas de latencia al eliminar un salto de red del camino crítico.
Componente del diagrama :MotorRiesgo decide sobre el perfil; :MotorParametrico sobre el umbral
Modelo donde está presente Modelo de Módulo
Escenario EC-LAT-03 — p95 ≤ 400 ms
ASR HA-03

Por qué esta decisión. En una arquitectura distribuida cada decisión que se toma lejos de su dato cuesta un viaje de red, y ese viaje se descuenta de un presupuesto de 400 ms del que 120 ms ya están comprometidos por dependencia externa. La alternativa natural —un motor de reglas central que decidiera por todos los dominios— habría sido más fácil de gobernar, pero obligaría a que perfilamiento le enviara el perfil completo y esperara, y convertiría ese motor en cuello de botella común y en punto único de acoplamiento. Se prefirió pagar en gobierno (dos motores en vez de uno) para no pagar en latencia, poniendo cada decisión pegada al componente que ya tiene la información para tomarla.

Patrón Experto


2.7.7 Alta Cohesión (GRASP)

Táctica que aterriza Mantener alta cohesión (modificabilidad): que las responsabilidades de cada componente estén ligadas a un único propósito.
Componente del diagrama Paquete Dominio · Venta; :MotorRaiting como única razón de cambio del precio
Modelo donde está presente Modelo de Módulo
Escenario EC-MOD-03 — regla de precio
ASR HA-26

Por qué esta decisión. El precio y la política de aceptación de riesgo cambian con una frecuencia que dicta actuaría, no ingeniería, y cambian por razones distintas entre sí. Si esa lógica viviera dentro de los orquestadores, cada ajuste de fórmula obligaría a redesplegar la cotización completa y a arrastrar en el mismo despliegue código que no cambió. Se separó el motor de quien lo orquesta para que la unidad de cambio coincida con la unidad de despliegue, que es la condición que EC-MOD-03 mide: el 100 % del cambio se despliega sin tocar componentes ajenos al motor de rating.

Patrón Alta Cohesión


2.7.8 Bajo Acoplamiento (GRASP)

Táctica que aterriza Reducción del acoplamiento (modificabilidad). Es precondición de múltiples copias de computación: solo se replica de forma independiente lo que no arrastra a sus vecinos.
Componente del diagrama Interfaces provided/required entre componentes; :BusEventos como intermediario; capa de adaptadores
Modelo donde está presente Modelo de Módulo
Escenarios EC-MOD-05 · EC-INT-04
ASR HA-28 · HA-31

Por qué esta decisión. El bajo acoplamiento se suele justificar solo por modificabilidad, pero en este caso es precondición de los dos atributos priorizados: solo se puede replicar de forma independiente aquello que no arrastra a sus vecinos. Si :MsCotización dependiera de la implementación de sus colaboradores, escalarla obligaría a escalarlos con ella y desaparecería la ventaja de tener curvas de carga separadas. Por eso se aplicaron los tres mecanismos del catálogo a la vez —interfaz, intermediario orientado a mensajes y adaptador— en lugar de conformarse con uno. Se aceptó más piezas y más contratos que mantener a cambio de que el escalamiento selectivo sea realmente posible.

Patrón Bajo Acoplamiento


2.7.9 Inversión de dependencias (SOLID)

Táctica que aterriza Reducción del acoplamiento (modificabilidad), en su forma más estricta: el dominio no controla el ciclo de vida de su colaborador.
Componente del diagrama Contratos entre el dominio y la capa de adaptadores
Modelo donde está presente Modelo de Módulo
Escenarios EC-MOD-05 · EC-INT-03
ASR HA-28 · HA-30

Por qué esta decisión. Tener adaptadores no basta: si el dominio conociera al adaptador concreto y controlara su creación, seguiría atado a una implementación y el beneficio se perdería en el primer cambio de proveedor. Invertir la dependencia significa que el dominio declara qué necesita y recibe una abstracción ya construida, sin saber quién la implementa ni gestionar su ciclo de vida. Ese detalle es lo que convierte la contención del cambio en una propiedad verificable: por eso EC-MOD-05 puede exigir que el 100 % del cambio quede dentro del módulo de integración, y EC-INT-03 que el 100 % de los consumidores existentes siga operando sin modificación.

Patrón Inversión de dependencias


2.7.10 Creador (GRASP)

Táctica que aterriza Reducción del acoplamiento (modificabilidad): concentrar la creación en un solo responsable evita que varios objetos dependan entre sí para instanciarse.
Componente del diagrama :MsCotización crea la oferta; :MsSiniestros crea la evidencia y la evaluación
Modelo donde está presente Modelo de Módulo y modelo de dominio
Escenario EC-MOD-01
ASR HA-25

Por qué esta decisión. En una arquitectura de microservicios con base de datos por servicio, la pregunta de quién instancia cada entidad no es un detalle de código: determina qué servicio es dueño de su ciclo de vida y, por lo tanto, de su almacén. Si un componente ajeno creara la evidencia de un siniestro, tendría que conocer el estado de la reclamación y quedaría acoplado al servicio que la gobierna, rompiendo la frontera del dato. Aplicar la regla de que crea quien contiene y usa estrechamente al objeto confina el ciclo de vida de cada entidad a su microservicio, que es la precondición del almacén propio por servicio y de la trazabilidad entre las tres vistas: componente que crea → entidad de dominio → esquema propietario.

Patrón Creador


2.7.11 Única Responsabilidad (SRP) y Abierto/Cerrado (OCP)

Táctica que aterriza Mantener alta cohesión y reducción del acoplamiento (modificabilidad): unidades pequeñas, con una sola razón de cambio y un punto de extensión propio.
Componente del diagrama Tres pares orquestador / motor: :MsCotización–:MotorRaiting, :MsPerfilamiento–:MotorRiesgo, :MsSiniestros–:MotorParametrico
Modelo donde está presente Modelo de Módulo
Escenarios EC-MOD-01 · EC-MOD-04
ASR HA-25 · HA-27

Por qué esta decisión. El negocio de Solventa crece incorporando ramos: viaje, dispositivos, microseguros de vida, paramétricos, protección de pagos. Si cada ramo nuevo obligara a modificar los orquestadores, el costo de crecer aumentaría con el tamaño del portafolio y la meta de expansión regional se volvería inviable. Al concentrar la variabilidad del negocio en los motores, cada motor tiene una sola razón de cambio (SRP) y a la vez es el único punto por donde el producto se extiende (OCP). Son las dos caras de la misma decisión: lo que hace barato modificar es exactamente lo que hace barato extender. Que el patrón aparezca tres veces, y no una, es lo que lo convierte en principio aplicado y no en coincidencia.

Principios SRP y OCP


2.8 Trade-offs asumidos

Un trade-off es lo que se sacrifica para conseguir algo. Ninguna decisión mejora todos los atributos a la vez; lo que sigue no son defectos ni deuda pendiente, sino decisiones conscientes con su mitigación.

Decisión Se gana Se sacrifica Mitigación
Microservicios sobre monolito modular Escalamiento selectivo por curva de carga Latencia de red interna, complejidad operativa Presupuesto de latencia por salto; fronteras alineadas con capacidades de negocio para evitar el monolito distribuido
:BusEventos para el flujo paramétrico Absorción de picos; consumidores nuevos sin tocar productores Consistencia eventual Idempotencia por clave de evento
:CacheOF / :CacheOD en el camino crítico Presupuesto protegido ante terceros degradados Decidir con datos menos frescos TTL por fuente + linaje de toda cotización resuelta con respaldo
:ColaPagos solo en :MsPagos, no en los demás dominios Durabilidad y reintento idempotente donde se mueve dinero Asimetría respecto de los demás recorridos Es deliberada: el flujo de dinero exige durabilidad y aplicación exactamente una vez, exigencia que los demás recorridos no tienen
:ApiGateway como punto único Enmascaramiento de fallas y superficie de ataque reducida Un salto extra en el camino crítico y un punto de congestión Replicado y multi-zona; sin lógica de negocio en el gateway
Escalamiento horizontal como decisión por defecto Elasticidad y tolerancia a la falla de una zona Mayor tiempo de aprovisionamiento en la rampa inicial Escalamiento vertical de los motores de cálculo para cubrir los primeros segundos del pico

2.9 Fuentes

  • Enunciado del caso: files/MISW4501-202614-Proyecto.pdf — §4 Ecosistema de integraciones, §6.1 Latencia, §6.2 Escalabilidad, §8 Decisiones de arquitectura, §9 Preguntas de discusión.
  • Hoja de trabajo — objetivos de negocio y escenarios de calidad EC-*.
  • Visión de arquitectura — modelos de contexto, dominio, componentes, datos y despliegue.

3. Diseño del experimento de arquitectura


3.1 Experimento 1 — HA-08: Modelo de lectura de baja latencia para el estado de siniestro


3.1.1 Ficha del experimento

Campo Detalle
Título del experimento Modelo de lectura de baja latencia para el estado de siniestro mediante CQRS con proyección materializada y caché
Propósito del experimento Evaluar si las tácticas de latencia propuestas para la consulta de estado de siniestro —desacoplar el modelo de lectura del de escritura, materializar una proyección desnormalizada y servirla desde un almacén en memoria— permiten cumplir el ASR EC-LAT-11 (p95 ≤ 150 ms), y determinar cuál es el nivel mínimo de complejidad que lo satisface.
Resultados esperados Se espera que la lectura directa sobre el modelo transaccional normalizado no alcance el umbral bajo la carga de operación regular, que la proyección materializada reduzca el p95 de forma sustancial, y que el caché en memoria aporte una mejora adicional. El experimento debe además cuantificar el costo de esas tácticas en términos de staleness (lag de proyección) para determinar si la consistencia eventual resultante es aceptable para el escenario.
Elementos de arquitectura involucrados ASR asociado: EC-LAT-11 — Latencia, prioridad (A,A).
Historia de arquitectura: HA-08.
Vistas y modelos: Vista funcional (modelo de componentes: API de consulta, almacenes de lectura y escritura); Vista de información ; Vista de despliegue (modelo de contenedores).
Puntos de sensibilidad que se desean probar: separación del modelo de lectura, política de caché (TTL e invalidación) y tasa de llegada de consultas.
Esfuerzo estimado Tiempo: 1,5 semanas — 60 horas
Horas hombre: 15 horas/hombre (4 integrantes)
Recursos requeridos

Lista de recursos requeridos para ejecutar el experimento (software, librerías, hardware):

  • Lenguaje y framework: Python 3.12, FastAPI, Uvicorn
  • Contenerización: Docker y Docker Compose V2
  • Almacenamiento: PostgreSQL 16 (modelo transaccional y proyección), Redis 7 (caché)
  • Mensajería: Redpanda (API compatible con Kafka)
  • Librerías: asyncpg, redis-py (asyncio), aiokafka, orjson, pydantic, prometheus-client
  • Generación de carga: k6
  • Observabilidad: Prometheus, Grafana
  • Hardware: estación de desarrollo con mínimo 16 GB de RAM, 4 núcleos y 20 GB de disco libre (el dataset sintético ocupa ~2 GB más índices)

3.1.2 Hipótesis de diseño

Enunciado

Si separamos el modelo de lectura del de escritura mediante CQRS, materializando el estado del siniestro en una proyección desnormalizada (un registro autocontenido por siniestro) mantenida de forma asíncrona por un proyector que consume los eventos de dominio del proceso de evaluación, y servimos esa proyección desde un almacén clave-valor en memoria con fallback a la proyección persistente,

entonces la consulta de estado de siniestro alcanzará un p95 ≤ 150 ms bajo la carga esperada en producción regular,

aceptando como contrapartida consistencia eventual acotada (lag de proyección p95 ≤ 2 s), duplicación de datos y mayor complejidad operativa.

Campo Detalle
Historia de arquitectura asociada HA-08 — Modelo de lectura de baja latencia para el estado de siniestro
Escenario de calidad EC-LAT-11 — Latencia, prioridad (A,A), clasificado como ASR
Nivel de incertidumbre Medio-Alto. El equipo tiene experiencia previa con CQRS, pero desconoce (a) si la proyección por sí sola basta o si el caché es indispensable, (b) cuánto lag introduce el proyector bajo carga concurrente de lectura, y (c) cuál es el punto de quiebre de cada alternativa. El costo de equivocarse es alto: revertir CQRS una vez adoptado implica reescribir el camino de lectura y el proceso de evaluación completo.
Puntos de sensibilidad
# Punto de sensibilidad ¿Qué probar?
1 Grado de separación del modelo de lectura. Es la decisión arquitectónica central: cuánta separación entre comando y consulta se requiere para satisfacer el ASR. Variar la estrategia de lectura en tres niveles: A lectura directa sobre el modelo transaccional normalizado (sin separación), B proyección materializada persistente (separación lógica y física del esquema), C proyección + caché en memoria (separación con copia adicional en otro medio de almacenamiento).
2 Política del caché. Determina el balance entre latencia y staleness, que es el trade-off que la historia HA-08 pone en tensión: el cliente quiere inmediatez, pero también quiere ver el estado vigente. Variar el TTL del caché: 0 s (sin caché, equivale al brazo B), 30 s (valor propuesto) y 300 s. Medir simultáneamente el p95 y el lag observado por el cliente.
3 Tasa de llegada de consultas. Identifica el margen de crecimiento de cada alternativa antes de incumplir el ASR. Escalones de 10, 25, 50 y 80 solicitudes por segundo, registrando el p95 en cada escalón para localizar el punto de quiebre de cada brazo.

3.1.3 Estilos de arquitectura asociados al experimento

Estilo de arquitectura asociado al experimento Análisis (atributos de calidad que favorece y desfavorece)
CQRS (segregación de responsabilidades de comando y consulta) Favorece:
• Latencia de lectura
• Escalabilidad independiente de lectura y escritura
• Modificabilidad del esquema de consulta
• Disponibilidad de la consulta ante presión sobre el modelo transaccional

Desfavorece:
• Consistencia (pasa de fuerte a eventual)
• Simplicidad operativa (componente adicional con modos de falla propios)
• Testabilidad extremo a extremo
• Eficiencia de almacenamiento (datos duplicados)
Arquitectura orientada a eventos (publicación/suscripción) Favorece:
• Desacople entre el proceso de evaluación y el modelo de lectura
• Escalabilidad del procesamiento asíncrono
• Integrabilidad con futuros consumidores (notificaciones, analítica)

Desfavorece:
• Consistencia inmediata
• Trazabilidad y depuración del flujo
• Complejidad de la infraestructura (broker, particiones, consumer groups)
Microservicios (contexto general de Solventa) Favorece:
• Disponibilidad
• Escalabilidad
• Mantenibilidad
• Flexibilidad tecnológica

Desfavorece:
• Latencia extremo a extremo (saltos de red adicionales)
• Orquestación/coreografía
• Consistencia distribuida

La tensión que resuelve este experimento es visible en la tabla: el estilo de microservicios, ya adoptado en Solventa, desfavorece la latencia, y HA-08 es precisamente un ASR de latencia. CQRS se introduce como contramedida deliberada a esa contrapartida, no como preferencia estilística.


3.1.4 Tácticas de arquitectura asociadas al experimento

Táctica de arquitectura asociada al experimento Descripción
Reducir la demanda computacional Para el sistema Solventa, el estado de un siniestro se compone hoy a partir de cinco entidades normalizadas (siniestro, póliza, hitos, documentos y peritaje), lo que obliga a la consulta a resolver joins y agregaciones en tiempo de petición. La táctica consiste en trasladar ese cómputo fuera del camino crítico: el proyector construye el estado completo una sola vez, en el momento en que ocurre el evento, y lo almacena listo para entregar. La consulta pasa a ser un acceso por clave primaria sin joins ni agregaciones.
Mantener múltiples copias de los datos Se introducen dos copias derivadas del estado del siniestro: una proyección persistente en PostgreSQL, desnormalizada y con un registro por siniestro, y una copia volátil en Redis servida desde memoria. Cada copia acorta el camino de acceso a costa de introducir una ventana de desactualización que debe ser medida y acotada.
Introducir concurrencia La actualización del modelo de lectura se ejecuta en un componente independiente (el proyector), que consume los eventos de dominio de forma asíncrona y trabaja en paralelo a las consultas de los clientes. El cliente nunca espera a que la proyección se actualice.
Reducir el overhead de procesamiento El estado se almacena ya serializado (JSONB en la proyección, JSON en el caché) y se emplea un serializador de alto desempeño en la respuesta HTTP, de modo que la representación no se reconstruye en cada petición.

3.1.5 Listado de componentes involucrados en el experimento

Componente Propósito y comportamiento esperado Tecnología asociada
API de Consulta de Siniestros Expone el recurso de consulta de estado de siniestro. Debe implementar los tres brazos del experimento sobre el mismo binario, seleccionables por configuración, de modo que la estrategia de lectura sea la única variable que cambie entre corridas. Devuelve una representación idéntica en los tres brazos. Python, FastAPI, Uvicorn (uvloop), asyncpg, redis-py, orjson
Proyector de Estado de Siniestro Consume los eventos de dominio del proceso de evaluación y actualiza la proyección materializada de forma idempotente. Debe descartar eventos con versión anterior a la almacenada e invalidar la entrada correspondiente del caché. Expone el lag de proyección como métrica. Python, aiokafka, asyncpg, redis-py, prometheus-client
Simulador del Proceso de Evaluación Genera cambios de estado sobre siniestros del conjunto caliente a una tasa configurable, escribiendo en el modelo transaccional y publicando el evento correspondiente. Mantiene la proyección bajo actualización activa durante toda la medición, condición exigida por el escenario EC-LAT-11. Python, aiokafka, asyncpg
Almacén Transaccional Contiene el modelo normalizado del proceso de evaluación. Es el origen de la verdad y la fuente de lectura del brazo A. Debe conservar sus índices para que la línea base sea una implementación razonablemente optimizada. PostgreSQL 16, esquema siniestros_w
Almacén de Proyección Contiene la vista materializada, un registro autocontenido por siniestro con la respuesta preconstruida. Es la fuente de lectura del brazo B y el respaldo del brazo C. PostgreSQL 16, esquema siniestros_r
Caché de Estado Almacena en memoria las entradas más consultadas bajo una política cache-aside con expiración e invalidación proactiva desde el proyector. Redis 7

3.1.6 Listado de conectores involucrados en el experimento

Conector Comportamiento deseado en el experimento Tecnología asociada
Conector HTTP de consulta El generador de carga emite solicitudes contra el recurso de estado de siniestro a una tasa de llegada fija (no un número fijo de usuarios), de modo que la degradación del servicio no reduzca automáticamente la carga y enmascare el p95. Registra la latencia extremo a extremo por solicitud. Cliente: k6 con ejecutor de tasa de llegada escalonada. Servidor: Uvicorn sobre ASGI.
Conector de eventos asíncrono Cada cambio de estado del proceso de evaluación se publica como un evento particionado por identificador de siniestro, lo que garantiza el orden por agregado. Un consumidor perteneciente a un grupo dedicado procesa los eventos y actualiza la proyección. El evento transporta el estado completo (event-carried state transfer), de modo que el proyector nunca consulta de vuelta el modelo de escritura y el desacople exigido por HA-08 se preserva. Publicador: aiokafka producer. Broker: Redpanda. Consumidor: aiokafka consumer con consumer group.
Conector de acceso transaccional (brazo A) Resuelve la consulta componiendo el estado a partir de las cinco entidades normalizadas mediante joins y agregaciones en tiempo de petición. Representa la línea base contra la cual se mide la mejora. asyncpg sobre PostgreSQL, esquema siniestros_w. Pool de conexiones de tamaño fijo.
Conector de acceso a la proyección (brazos B y C) Resuelve la consulta mediante un acceso por clave primaria a un único registro, sin joins ni agregaciones. asyncpg sobre PostgreSQL, esquema siniestros_r.
Conector de caché (brazo C) Implementa cache-aside: ante un acierto devuelve la entrada en memoria; ante un fallo consulta la proyección, entrega el resultado y escribe la entrada con expiración. El proyector invalida la entrada al aplicar un cambio de estado, de modo que el caché nunca sirve una versión anterior a la ya proyectada. redis-py en modo asíncrono sobre Redis 7, política allkeys-lru.
Conector de telemetría La API y el proyector exponen métricas en formato de texto plano que Prometheus recolecta periódicamente; el generador de carga envía sus métricas por escritura remota al mismo Prometheus, de modo que latencia de cliente y de servidor queden en la misma línea de tiempo y sean comparables. prometheus-client (exposición), Prometheus (scrape y remote-write receiver), Grafana (visualización).

3.1.7 Tecnología asociada con el experimento

Tecnología asociada con el experimento Selección Justificación
Lenguajes de programación Python 3.12 Alineado con el stack del equipo y con el resto de componentes de Solventa. Su modelo asíncrono permite representar fielmente el comportamiento de un servicio de lectura con E/S intensiva.
Frameworks de desarrollo FastAPI + Uvicorn (uvloop, httptools) Framework ASGI nativo asíncrono, necesario para que el camino de lectura no bloquee el event loop. Uvicorn con uvloop reduce el overhead del servidor, de modo que la latencia medida refleje la estrategia de lectura y no el transporte.
Plataforma de despliegue Docker + Docker Compose V2 Permite fijar límites explícitos de CPU y memoria por componente, condición indispensable para que las corridas sean reproducibles y comparables entre brazos en una estación de desarrollo.
Bases de datos PostgreSQL 16 (esquemas siniestros_w y siniestros_r)
Redis 7
PostgreSQL sostiene tanto el modelo normalizado como la proyección, lo que aísla la variable bajo estudio: la diferencia entre brazos A y B proviene del modelo de datos, no del motor. Redis aporta el almacenamiento en memoria del brazo C.
Mensajería Redpanda API compatible con Kafka, con un consumo de recursos considerablemente menor en un nodo único, lo que es determinante en un montaje local donde el broker compite por CPU con el generador de carga.
Herramientas de análisis k6, Prometheus, Grafana k6 ofrece un ejecutor de tasa de llegada (imprescindible para medir latencia correctamente) y umbrales declarativos que permiten codificar el criterio de aceptación del ASR en el propio script. Prometheus y Grafana correlacionan latencia de cliente, latencia interna, lag de proyección y consumo de recursos en una misma línea de tiempo.
Librerías asyncpg, redis-py (asyncio), aiokafka, orjson, pydantic, prometheus-client Drivers asíncronos en toda la ruta de lectura, requisito no negociable: un driver síncrono dentro de una corrutina bloquea el event loop completo y produciría una refutación falsa de la hipótesis. orjson minimiza el costo de serialización, que de otro modo contaminaría la comparación entre brazos.

3.1.8 Distribución de actividades por integrante

Integrante Tareas a realizar Esfuerzo estimado
Alex Mauricio Rodriguez Sanchez Desarrollar la API de Consulta de Siniestros:
• Crear la aplicación FastAPI y el ciclo de vida de los pools.
• Implementar los tres brazos de lectura sobre el mismo binario.
• Instrumentar la latencia interna y el hit-rate del caché.
10,5 horas
Martin Ricardo Romero Ortiz Preparar el entorno de ejecución:
• Crear y configurar el docker-compose.yml con límites de recursos por componente.
• Configurar la red de Docker, PostgreSQL (parámetros de memoria), Redis y Redpanda.
• Configurar Prometheus, Grafana y el remote-write desde k6.
• Apoyar en la integración y ejecución de las corridas.
10,5 horas
John Edwin Guerrero Ayala Desarrollar el Proyector y el Simulador:
• Implementar el consumidor de eventos con upsert idempotente por versión.
• Implementar la invalidación del caché y la métrica de lag.
• Construir el simulador del proceso de evaluación sobre el conjunto caliente.
10,5 horas
Juan Camilo Acevedo Ospina Planificar y dirigir el experimento:
• Definir el contrato del evento de dominio y el modelo de la proyección.
• Generar el dataset sintético y verificar que el volumen supere la memoria del motor.
• Construir el script de carga y el protocolo de corridas contrabalanceadas.
• Analizar los resultados y redactar el informe final.
10,5 horas

Total: 42 horas — 1 semana

El esfuerzo debe recalibrarse una vez conocida la duración real de la generación del dataset, que es la actividad con mayor incertidumbre del cronograma.


3.2 Experimento 2 — HA-01: Protección del presupuesto de latencia de la cotización embebida

Protección del presupuesto de latencia de la cotización embebida frente a una dependencia externa de Open Finance

Atributo priorizado Latencia (desempeño)
Modelos de referencia §1.2 Vista funcional · §1.3 Vista de despliegue

Este experimento valida la respuesta que la wiki da a la pregunta 3 del enunciado (¿cómo se protege el presupuesto de latencia de la cotización cuando depende de un proveedor externo de Open Finance más lento e impredecible?). Esa respuesta —§1.2.4— afirma que :CacheOF ya tiene el perfil y que la llamada a :AdaptadorOF es una actualización oportunista y no una dependencia bloqueante. Hoy es un argumento de diseño sin evidencia.


3.2.1 Ficha del experimento

Campo Detalle
Título del experimento Caché con actualización oportunista y valor de respaldo para proteger el presupuesto de latencia de la cotización embebida ante un proveedor de Open Finance degradado
Propósito del experimento Evaluar si la distribución de componentes propuesta —:MsCotización → :CacheOF → :AdaptadorOF → proveedor externo, con la llamada al adaptador fuera del camino bloqueante— permite cumplir EC-LAT-01 (p95 ≤ 250 ms) y EC-LAT-02 (p99 ≤ 500 ms) tanto con el proveedor sano como degradado (EC-LAT-09), y determinar cuál es el nivel mínimo de desacople que lo satisface. El montaje no incluye el :ApiGateway, de modo que los umbrales se trasladan al servicio descontando el presupuesto de borde (Anexo G).
Resultados esperados Se espera que la llamada síncrona bloqueante al proveedor no alcance el umbral cuando este se degrada, que la caché con lectura bloqueante en fallo lo alcance solo si la tasa de acierto es muy alta, y que la caché con actualización oportunista lo alcance de forma estable e independiente del estado del proveedor. El experimento debe cuantificar el costo de esa independencia en dos dimensiones: la frescura del dato con que se tarifica y la proporción de cotizaciones resueltas con valor de respaldo. Se espera además confirmar el resultado contraintuitivo previsto por el equipo: el camino degradado resulta más rápido que el camino frío con proveedor sano.
Elementos de arquitectura involucrados ASR asociados: EC-LAT-01 y EC-LAT-02 — Latencia, prioridad (A,A); EC-LAT-09 — Latencia con dependencia degradada, prioridad (A,A). Restricciones de presupuesto: EC-LAT-07 (≤ 120 ms por dependencia externa) y EC-LAT-08 (timeout duro de 700 ms).
Historia de arquitectura: HA-01 — verificar el identificador en Jira antes de publicar.
Vistas y modelos: Vista funcional (:MsCotización, :MotorRaiting, :CacheOF, :AdaptadorOF); Vista de despliegue (ElastiCache Redis y grupo de escalado de cotización); Vista de información (§1.4.4, valor de respaldo; §1.4.3, estrategia de replicación).
Correspondencia con el diagrama de componentes: el montaje no introduce componentes nuevos. Cada pieza corresponde a un «component» o «datastore» ya publicado en §1.2, salvo el inyector de fallas y el doble del proveedor, que son instrumentación y se declaran como tales.
Puntos de sensibilidad que se desean probar: grado de bloqueo de la dependencia externa, tasa de acierto de la caché, estado del proveedor, política del interruptor y tasa de llegada.
Esfuerzo estimado Tiempo: 1,5 semanas — 56 horas
Horas hombre: 14 horas/hombre (4 integrantes)
Menor que HA-08 porque se reutiliza el montaje de contenedores, el stack de observabilidad y el protocolo de corridas ya construidos.
Recursos requeridos
  • Lenguaje y framework: Python 3.12, FastAPI, Uvicorn (uvloop, httptools)
  • Contenerización: Docker y Docker Compose V2
  • Almacenamiento: Redis 7 (:CacheOF), PostgreSQL 16 (catálogo de producto y reglas de tarifa)
  • Cliente HTTP asíncrono: httpx con límites de conexión explícitos por proveedor
  • Doble del proveedor de Open Finance: servicio FastAPI que devuelve el contrato real de Open Finance con una distribución de latencia de aplicación configurable (no un valor fijo)
  • Inyección de fallas de red: Toxiproxy, interpuesto entre :AdaptadorOF y el doble, para degradación a nivel de conexión TCP
  • Librerías: httpx, redis-py (asyncio), asyncpg, orjson, pydantic, prometheus-client
  • Generación de carga: k6 con ejecutor de tasa de llegada
  • Observabilidad: Prometheus, Grafana
  • Hardware: estación de desarrollo con mínimo 16 GB de RAM, 4 núcleos y 10 GB de disco libre. El dataset es mucho menor que el de HA-08: no hay millón de registros, sino un conjunto de perfiles de Open Finance del tamaño del universo de clientes simulado.

3.2.2 Hipótesis de diseño

Enunciado

Si :MsCotización resuelve el perfil de Open Finance leyendo :CacheOF y trata la invocación de :AdaptadorOF como una actualización oportunista —abandonando la espera al agotar el presupuesto por dependencia de 120 ms (EC-LAT-07) y resolviendo con el último valor conocido o con un valor por defecto—, mientras :AdaptadorOF conserva su timeout duro de 700 ms (EC-LAT-08) con circuit breaker y aislamiento de recursos por proveedor,

entonces la cotización embebida alcanzará un p95 ≤ 225 ms y un p99 ≤ 475 ms medidos en el servicio —equivalentes a 250 ms y 500 ms extremo a extremo una vez sumado el presupuesto de borde del Anexo G— con el proveedor sano y también con el proveedor degradado o caído,

aceptando como contrapartida que una fracción acotada de las cotizaciones se tarifique con señales menos frescas o con valores por defecto, que esa fracción quede trazada para actuaría, y que un conjunto reducido de peticiones se sacrifique durante la apertura del interruptor.

Campo Detalle
Historia de arquitectura asociada HA-01 — Protección del presupuesto de latencia de la cotización embebida
Escenarios de calidad EC-LAT-01 y EC-LAT-02 (operación normal y horario pico), EC-LAT-09 (dependencia degradada). Restricciones: EC-LAT-07, EC-LAT-08
Nivel de incertidumbre Alto. La separación de los dos timeouts en componentes distintos es una lectura del equipo, no una prescripción del enunciado: el caso da ambos números sin decir a quién pertenecen. Se desconoce (a) cuántas peticiones se sacrifican antes de que el interruptor abra y si ese conjunto rompe el p99, (b) si el umbral por conteo abre a tiempo con tráfico bajo, (c) si las llamadas abandonadas por :MsCotización agotan el pool de :AdaptadorOF bajo carga, y (d) qué tasa de acierto de caché es necesaria para sostener el escenario. El costo de equivocarse es alto: si el diseño no se sostiene, la cotización embebida —el journey que define la propuesta de valor de Solventa— incumple su ASR frente a un proveedor que Solventa no controla.
Puntos de sensibilidad
# Punto de sensibilidad ¿Qué probar?
1 Grado de bloqueo de la dependencia externa. Es la decisión arquitectónica central: cuánto puede el camino crítico depender de un tercero impredecible. Variar la estrategia de resolución del perfil en tres niveles: A invocación síncrona bloqueante al adaptador en cada cotización, sin caché; B caché con lectura bloqueante en fallo (cache-aside clásico: el fallo espera al proveedor); C caché con actualización oportunista y valor de respaldo (el diseño propuesto: la respuesta nunca espera al proveedor).
2 Estado del proveedor externo. EC-LAT-09 exige cumplir el umbral con la dependencia degradada, no solo en condiciones ideales. Cinco estados, más la transición de recuperación. Ver el modelo de fallas del Anexo A: sano, lento, degradado, sin respuesta (acepta la conexión y nunca contesta) y caído (conexión rechazada). El estado sin respuesta es el más hostil y el que realmente pone a prueba el pool del adaptador.
3 Tasa de acierto de la caché. Es la variable que decide si el camino frío define o no el percentil. El diseño se sostiene solo por encima de cierto umbral, y ese umbral hoy no está cuantificado. Preparar el conjunto de claves consultadas para producir tasas de acierto de 99 %, 96 %, 90 % y 50 %, midiendo el p95 y el p99 en cada nivel para localizar el punto de quiebre.
4 Política del circuit breaker. Un umbral por conteo abre rápido con tráfico alto y tarde con tráfico bajo; en el segundo caso las peticiones sacrificadas pueden superar el 1 % de la ventana y romper el p99. Comparar umbral por conteo (N fallos consecutivos) contra umbral por tasa sobre ventana deslizante, en dos niveles de tráfico: alto (200 sol/s) y bajo (10 sol/s).
5 Concurrencia sobre la misma clave (estampida). Varias peticiones concurrentes con fallo sobre el mismo perfil dispararían N invocaciones idénticas al proveedor justo cuando más duele. Brazo adicional C' = C más coalescencia de peticiones (single-flight), midiendo invocaciones al proveedor por fallo de caché y saturación del pool del adaptador.
Sub-hipótesis
ID Enunciado Punto de sensibilidad Brazos
HD-01.1 Con el proveedor sano, los tres brazos cumplen p95 ≤ 225 ms 1, 2 A, B, C
HD-01.2 Con el proveedor degradado, solo el brazo C cumple p95 ≤ 225 ms y p99 ≤ 475 ms 1, 2 A, B, C
HD-01.3 En el brazo C, el camino degradado es más rápido que el camino frío con proveedor sano 1, 2 C
HD-01.4 El brazo C sostiene el umbral con tasa de acierto ≥ 96 %; por debajo de ese valor el p99 se degrada 3 B, C
HD-01.5 Las peticiones sacrificadas hasta la apertura del interruptor son < 1 % de la ventana con tráfico alto 4 C
HD-01.6 Con tráfico bajo, el umbral por conteo no mantiene las sacrificadas bajo el 1 %, y el umbral por tasa sí 4 C
HD-01.7 Sin coalescencia, un fallo concurrente sobre la misma clave produce más de una invocación al proveedor y satura el pool del adaptador antes que con coalescencia 5 C, C'
HD-01.8 Al recuperarse el proveedor, el interruptor cierra y la proporción con respaldo vuelve por debajo del 5 % en ≤ 60 s, sin producir una estampida de invocaciones 2, 5 C, C'

HD-01.6 es deliberadamente refutable en su forma afirmativa. Si el umbral por conteo resulta suficiente también con tráfico bajo, el equipo se ahorra una complejidad; si no, tiene evidencia para justificarla. En ambos casos el experimento decide algo.


3.2.3 Estilos de arquitectura asociados al experimento

Estilo Análisis (atributos de calidad que favorece y desfavorece)
Llamada-retorno sincrónico (N-niveles) Favorece:
• Baja latencia interna y consistencia inmediata en el journey de venta
• Simplicidad de razonamiento y de depuración
Desfavorece:
• Acoplamiento temporal con el colaborador
• Propagación de la latencia y de la falla del tercero al camino crítico
Capas + adaptadores (anticorrupción) Favorece:
• Modificabilidad e integrabilidad ante el cambio de proveedor
• Punto único donde alojar timeout, interruptor y aislamiento de recursos
Desfavorece:
• Una indirección más por llamada
• Riesgo de que el adaptador se vuelva cuello de botella si no se le acota el pool
Microservicios (contexto general de Solventa) Favorece:
• Escalamiento selectivo de :MsCotización según la curva de campaña de un socio
• Modificabilidad
Desfavorece:
• Latencia extremo a extremo por los saltos de borde
• Consistencia distribuida

Precisión sobre el origen del costo de latencia. A diferencia de HA-08 —donde el costo provenía de componer el estado sobre cinco entidades normalizadas— aquí el costo es externo y ajeno al control de Solventa: proviene de la latencia y la variabilidad del proveedor de Open Finance. Ningún estilo interno lo elimina; lo único que la arquitectura puede hacer es sacarlo del camino bloqueante. Ese es el objeto exacto del experimento, y la razón por la que el brazo A no es un hombre de paja sino la implementación que cualquier equipo escribiría primero.


3.2.4 Tácticas de arquitectura asociadas al experimento

Táctica (nombre del catálogo) Familia Descripción en este experimento
Múltiples copias de datos II :CacheOF conserva una copia local del perfil de Open Finance con su marca de tiempo. Es la táctica que la wiki ya declara en §1.2.1 para EC-LAT-09, y la que este experimento pone a prueba. La copia acorta el camino de acceso a costa de introducir una ventana de desactualización que debe medirse, no suponerse.
Incrementar la latencia de los recursos I El presupuesto por dependencia de 120 ms es un límite explícito sobre cuánto puede esperar el camino crítico. Al agotarse, :MsCotización abandona la espera en lugar de propagar el retraso del tercero.
Limitar la respuesta a los eventos I La actualización del perfil se ejecuta fuera de la respuesta al socio: la invocación al adaptador continúa en segundo plano y su resultado sirve para repoblar la caché, no para responder.
Detección de fallas: temporizador Disponibilidad El timeout duro de 700 ms en :AdaptadorOF (EC-LAT-08) es el detector que alimenta al circuit breaker.
Recuperación: degradación elegante Disponibilidad Ante la ausencia de perfil fresco, :MsCotización tarifica con el último valor conocido o con el valor por defecto del ramo, y marca la cotización como resuelta con respaldo para trazabilidad actuarial.
Aislamiento de recursos (bulkhead) Disponibilidad Pool de conexiones y de trabajo dedicado por proveedor y por consumidor en :AdaptadorOF, de modo que las llamadas abandonadas no agoten los recursos del resto del servicio. Es la táctica que hace viable abandonar a los 120 ms sin efectos colaterales. Se dimensiona también sobre las tareas de refresco en segundo plano, no sólo sobre las conexiones, y PoolTimeout se excluye del cómputo de fallas del proveedor: la saturación propia no debe abrir el interruptor con el tercero sano.

3.2.5 Listado de componentes involucrados en el experimento

Componente Propósito y comportamiento esperado Tecnología asociada
API de Cotización
(:MsCotización del modelo de componentes)
Expone el recurso de cotización embebida. Implementa los cuatro brazos sobre el mismo binario, seleccionables por configuración, de modo que la estrategia de resolución del perfil sea la única variable que cambie entre corridas. Aplica el presupuesto por dependencia, decide entre perfil fresco, último valor conocido y valor por defecto, y marca la respuesta con el origen y la edad del dato usado. Python, FastAPI, Uvicorn, httpx, redis-py, orjson
Motor de Tarifa
(:MotorRaiting)
Calcula la prima a partir del perfil recibido y del conjunto de reglas vigente. Se implementa con un costo de cómputo fijo y calibrado (~60 ms) para que sea una constante entre brazos y no una fuente de variación. Debe aceptar perfiles incompletos y reflejar la incertidumbre en el resultado. Python, reglas versionadas en memoria, asyncpg para cargar el conjunto de reglas al arranque
Caché de Perfil de Open Finance
(:CacheOF)
Almacena el perfil por cliente con su marca de tiempo de obtención, bajo política de expiración por fuente. Sirve el último valor conocido incluso vencido cuando el proveedor no responde: la expiración marca cuándo conviene refrescar, no cuándo dejar de servir. Esta distinción es una decisión de diseño y una de las cosas que el experimento debe validar. Redis 7, política allkeys-lru
Adaptador de Open Finance
(:AdaptadorOF)
Traduce del esquema del proveedor al modelo canónico de señales. Aloja el timeout duro de 700 ms, el circuit breaker con sus tres estados y el pool dedicado por proveedor. Expone como métricas el estado del interruptor, las conexiones en vuelo y el tiempo hasta la apertura. Python, httpx con límites de conexión, interruptor implementado en el propio adaptador para poder instrumentar sus transiciones
Doble del Proveedor de Open Finance
(instrumentación, no arquitectura)
Sustituye al «External» :OpenFinance del modelo de componentes. Devuelve la forma real del contrato de Open Finance para que el costo de deserialización en el adaptador sea representativo, y aplica una latencia de aplicación muestreada de una distribución log-normal con cola larga, no un valor constante. Es sin estado y determinista bajo semilla fija, de modo que dos repeticiones sean comparables. Corre con límites de recursos propios y su saturación se verifica antes de cada corrida. Python, FastAPI, numpy para el muestreo
Inyector de Fallas de Red
(instrumentación, no arquitectura)
Se interpone entre el adaptador y el doble para degradar la conexión, no la aplicación: latencia de red, corte de conexión, rechazo y agujero negro. Se modifica en caliente por su API de administración, sin reiniciar el montaje, condición necesaria para recorrer los cinco estados dentro de una misma corrida. Toxiproxy

Los dos últimos componentes no existen en el modelo de arquitectura y no deben aparecer en él. Son el banco de pruebas. Se declaran aquí para que la trazabilidad entre el experimento y el diagrama de componentes sea explícita y no quede a interpretación del lector.


3.2.6 Listado de conectores involucrados en el experimento

Conector Comportamiento deseado en el experimento Tecnología asociada
Conector HTTP de cotización El generador de carga emite solicitudes contra el recurso de cotización a una tasa de llegada fija, de modo que la degradación del servicio no reduzca automáticamente la carga y enmascare el percentil. Registra la latencia extremo a extremo por solicitud y etiqueta cada una con el brazo, el estado del proveedor y el nivel de acierto configurado. Cliente: k6 con ejecutor de tasa de llegada. Servidor: Uvicorn sobre ASGI.
Conector de acceso a la caché Lectura por clave del perfil, devolviendo valor y marca de tiempo. En el brazo C la escritura ocurre fuera del camino de respuesta, alimentada por el resultado de la actualización oportunista. redis-py en modo asíncrono sobre Redis 7.
Conector de invocación al proveedor (brazo A) Invocación bloqueante en cada cotización, sin caché y sin presupuesto de abandono: el camino crítico espera lo que el proveedor tarde, hasta el timeout duro. Es la línea base y representa la implementación que se escribiría sin la táctica bajo estudio. httpx asíncrono con timeout de 700 ms.
Conector de invocación bloqueante en fallo (brazo B) Cache-aside clásico: ante un acierto responde de inmediato; ante un fallo invoca al proveedor y espera el resultado antes de responder. Aísla el efecto de la caché del efecto del desacople, que es la distinción que el experimento debe demostrar. httpx asíncrono, misma configuración de timeout.
Conector de actualización oportunista (brazos C y C') La invocación al proveedor se lanza con un presupuesto de 120 ms; al agotarse, la respuesta se resuelve con el último valor conocido o con el valor por defecto y la invocación continúa en segundo plano hasta su timeout duro, repoblando la caché si llega a completarse. El circuit breaker corta las invocaciones mientras esté abierto. En C' se añade coalescencia por clave. httpx con pool dedicado, asyncio.timeout para el presupuesto, tarea en segundo plano para el refresco, coalescencia por clave con asyncio.Future compartido.
Conector de inyección de fallas Permite alterar la latencia y la disponibilidad del proveedor sin reiniciar el montaje, condición necesaria para que los cuatro estados del proveedor se recorran dentro de una misma corrida y sean comparables sin efecto de calentamiento. Toxiproxy con API de administración.
Conector de telemetría La API y el adaptador exponen métricas que Prometheus recolecta periódicamente; el generador de carga las envía por escritura remota al mismo Prometheus, de modo que latencia de cliente, latencia interna, estado del interruptor y saturación del pool queden en la misma línea de tiempo. prometheus-client, Prometheus, Grafana.

3.2.7 Tecnología asociada con el experimento

Tecnología Selección Justificación
Lenguajes de programación Python 3.12 Alineado con el stack del equipo, con el resto de Solventa y con el experimento HA-08, lo que permite reutilizar montaje y protocolo. Su modelo asíncrono es indispensable para representar la actualización oportunista: la tarea de refresco debe seguir viva después de que la respuesta ya salió.
Frameworks de desarrollo FastAPI + Uvicorn (uvloop, httptools) Framework ASGI nativo asíncrono. Es requisito para el brazo C: un servidor síncrono no puede continuar una invocación en segundo plano después de responder sin bloquear un hilo del pool, lo que falsearía la comparación.
Cliente HTTP httpx en modo asíncrono, con limits explícitos por proveedor Permite fijar el tamaño del pool por destino, que es la implementación concreta del bulkhead, y separar el presupuesto de la petición del timeout de la conexión. Un cliente sin límites por destino haría imposible medir HD-01.7.

Corrección tras HA-01 (18/09/2026): el bulkhead por proveedor no basta. :AdaptadorOF tiene dos consumidores en el modelo publicado —:MsCotización (cotización embebida, EC-LAT-01/02/09) y :MsPerfilamiento (fan-out de originación, EC-LAT-03/04)— y §1.2.4 los separa precisamente porque sus curvas de carga no coinciden. Con un pool único por proveedor, el pico de cierre de mes de perfilamiento puede agotar el pool del que depende la cotización.

HA-01 midió el pool saturándose: 101 invocaciones en vuelo sobre un pool de 40 en la celda de estampida. Y como PoolTimeout se excluye deliberadamente de las fallas del proveedor, el interruptor no abriría: el camino de cotización se degradaría con el proveedor perfectamente sano y sin señal que lo explicara. El experimento ejercitó un solo consumidor, así que este acoplamiento no está medido.

El propio análisis de §2.3 ya anticipaba el riesgo —«que el adaptador se vuelva cuello de botella si no se le acota el pool»—. La decisión es dimensionar el pool por consumidor además de por proveedor, o declarar el acoplamiento como limitación aceptada. | circuit breaker | Implementación propia dentro de :AdaptadorOF | Se descarta una librería genérica porque el punto 4 de sensibilidad exige comparar dos políticas de apertura (conteo contra tasa sobre ventana deslizante) e instrumentar las transiciones de estado. Una librería obligaría a adaptar la instrumentación a su modelo interno y añadiría una variable ajena al estudio. | | Inyección de fallas | Toxiproxy | Es el estándar de facto para inyectar latencia y cortes a nivel de conexión TCP de forma reproducible y modificable en caliente por API. Inyectar la latencia dentro del doble del proveedor sería más simple, pero simularía un servidor lento y no una red degradada, que es el modo de falla que EC-LAT-09 describe. | | Doble del proveedor | Servicio FastAPI propio | Se prefiere sobre una herramienta de mocking general porque debe devolver la forma real del contrato de Open Finance para que el costo de deserialización en :AdaptadorOF sea representativo. | | Plataforma de despliegue | Docker + Docker Compose V2 | Permite fijar límites explícitos de CPU y memoria por componente, condición indispensable para que las corridas sean reproducibles y comparables entre brazos. Se reutiliza el archivo del experimento HA-08. | | Almacenamiento | Redis 7 (:CacheOF), PostgreSQL 16 (reglas de tarifa) | Redis corresponde a ElastiCache Redis de la vista de despliegue (§1.3). PostgreSQL solo sirve el conjunto de reglas al arranque y no participa del camino crítico, para que la variable bajo estudio sea únicamente la resolución del perfil. | | Herramientas de análisis | k6, Prometheus, Grafana | k6 ofrece el ejecutor de tasa de llegada, imprescindible para medir latencia correctamente, y umbrales declarativos que codifican el criterio de aceptación en el propio script. Grafana permite superponer el estado del interruptor sobre la curva de latencia, que es la visualización que hace evidente el hallazgo de HD-01.3. | | Librerías | httpx, redis-py (asyncio), asyncpg, orjson, pydantic, prometheus-client | Drivers asíncronos en toda la ruta: un driver síncrono dentro de una corrutina bloquea el event loop y produciría una refutación falsa. orjson minimiza el costo de serialización para que no contamine la comparación entre brazos. |


3.2.8 Distribución de actividades por integrante

Integrante Tareas a realizar Esfuerzo estimado
Alex Mauricio Rodriguez Sanchez Desarrollar la API de Cotización:
• Crear la aplicación FastAPI y el ciclo de vida de los clientes y pools.
• Implementar los cuatro brazos sobre el mismo binario.
• Implementar el presupuesto de abandono a 120 ms y la tarea de refresco en segundo plano.
• Instrumentar el origen y la edad del dato en cada respuesta.
10 horas
Martin Ricardo Romero Ortiz Preparar el entorno de ejecución:
• Extender el docker-compose.yml de HA-08 con Toxiproxy y el doble del proveedor.
• Configurar los cuatro estados del proveedor y el script que los conmuta en caliente.
• Configurar los tableros de Grafana con el estado del interruptor superpuesto a la latencia.
• Apoyar la ejecución de las corridas.
10 horas
John Edwin Guerrero Ayala Desarrollar el Adaptador y el Motor de Tarifa:
• Implementar :AdaptadorOF con timeout duro, pool dedicado y las dos políticas de interruptor.
• Instrumentar transiciones de estado, conexiones en vuelo y peticiones sacrificadas.
• Implementar el motor de tarifa con costo calibrado y tolerancia a perfiles incompletos.
• Implementar la coalescencia por clave del brazo C'.
10 horas
Juan Camilo Acevedo Ospina Planificar y dirigir el experimento:
• Definir el contrato del perfil canónico y la política de expiración por fuente.
• Construir el conjunto de claves que produce cada tasa de acierto objetivo.
• Construir el script de carga y el protocolo de corridas contrabalanceadas.
• Consolidar el presupuesto del Anexo G y redactar el informe final.
10 horas

Total: 40 horas — 1 semana

El esfuerzo asume que el montaje de contenedores y el stack de observabilidad de HA-08 están operativos y se reutilizan. Si el experimento se ejecuta de forma independiente, deben sumarse unas 12 horas de preparación de entorno.


3.3 Esfuerzo total de los experimentos

Total: 82 horas — 2 semanas trabajando con 4 arquitectos.

⚠️ **GitHub.com Fallback** ⚠️