Smart Proxy¶
1. Nombre del Patrón¶
- Nombre oficial: Smart Proxy
- Categoría: System Management (Gestión del Sistema de Mensajería)
- Traducción contextual: Proxy Inteligente
2. Resumen Ejecutivo¶
Smart Proxy es el patrón que introduce un intermediario inteligente entre un requestor y un servicio en un flujo request-reply, capaz de rastrear, enriquecer, transformar y gestionar la correlación de solicitudes y respuestas de forma transparente para ambas partes. A diferencia de un proxy simple que solo reenvía mensajes, un Smart Proxy entiende la conversación: mantiene estado sobre las solicitudes en vuelo, puede modificar la dirección de reply, enriquecer la respuesta con información adicional, y gestionar timeouts y fallos.
El problema que resuelve es de control y visibilidad en flujos request-reply: en un sistema de integración, cuando un requestor envía una solicitud a un servicio y espera una respuesta, el flujo es directo y opaco. No hay punto intermedio donde se pueda observar la conversación, medir latencia, aplicar políticas de timeout, enriquecer la respuesta o gestionar la correlación cuando el servicio downstream no soporta el correlation ID original.
La relevancia de este patrón es media-alta. En la arquitectura moderna, Smart Proxy se manifiesta en API gateways que rastrean request-reply conversations (Kong, AWS API Gateway), en service mesh sidecars (Envoy, Istio) que interceptan y enriquecen la comunicación entre servicios, en middleware de orquestación que coordina múltiples request-reply con servicios backend, y en sistemas de claims management que rastrean el estado de solicitudes a través de múltiples sistemas externos.
3. Definición Detallada¶
Propósito¶
Smart Proxy proporciona un intermediario que participa activamente en la conversación request-reply entre un requestor y un servicio. Su propósito es ofrecer un punto de control donde se puede rastrear el estado de la conversación, medir latencia, gestionar timeouts, enriquecer solicitudes y respuestas, y manejar la correlación entre request y reply cuando el servicio downstream no propaga directamente el correlation ID del requestor.
Lógica Arquitectónica¶
En un flujo request-reply simple, el requestor envía una solicitud a un canal de request y espera la respuesta en un canal de reply:
Este flujo es directo pero opaco: nadie más sabe que la conversación está en curso, no hay control sobre timeouts, y no hay oportunidad de enriquecer la respuesta. Smart Proxy se inserta en el flujo:
Requestor → Request Channel → Smart Proxy → Service Request Channel → Service
↑ ↓
← ← ← ← ← ← ← ← ← ← ← ← ← ← ← ←
Requestor ← Reply Channel ← Smart Proxy ← Service Reply Channel ← Service
El Smart Proxy:
- Intercepta la solicitud: recibe la solicitud del requestor.
- Registra el estado: almacena la correlación entre la solicitud original y la dirección de reply del requestor.
- Modifica el reply-to: cambia la dirección de reply para que la respuesta del servicio vuelva al proxy, no directamente al requestor.
- Reenvía la solicitud: envía la solicitud al servicio real.
- Recibe la respuesta: intercepta la respuesta del servicio.
- Enriquece/transforma: opcionalmente modifica la respuesta (añadir metadata, transformar formato, agregar información de latencia).
- Reenvía la respuesta: envía la respuesta al requestor original usando la dirección de reply almacenada.
- Limpia el estado: elimina el registro de la conversación completada.
Principio de Diseño Subyacente¶
El principio es interceptación transparente de conversaciones request-reply. El proxy es "smart" porque mantiene estado sobre las conversaciones en vuelo y puede tomar decisiones basadas en ese estado (timeout, retry, enriquecimiento). Es "transparente" porque ni el requestor ni el servicio necesitan saber que el proxy existe — ambos ven un flujo request-reply normal.
Problema Estructural que Resuelve¶
En sistemas distribuidos, los flujos request-reply tienen varias necesidades que no pueden satisfacerse sin un intermediario con estado:
- Tracking de conversaciones: ¿cuántas solicitudes están en vuelo? ¿Cuánto tiempo llevan esperando respuesta?
- Timeout management: si el servicio no responde en un tiempo razonable, ¿quién genera un timeout response?
- Correlation mapping: si el servicio downstream usa un correlation scheme diferente al del requestor, ¿quién mapea entre ambos?
- Response enrichment: si la respuesta del servicio necesita información adicional que el servicio no tiene (metadata del requestor, timestamps de tracking), ¿quién la añade?
- Cross-cutting policies: retry, circuit breaker, rate limiting, logging — aplicadas de forma centralizada a todas las conversaciones.
Contexto en el que Emerge¶
Smart Proxy emerge cuando los flujos request-reply requieren un nivel de control y visibilidad que no puede lograrse sin un intermediario. Típicamente en:
- Integraciones con servicios externos (partners, proveedores) donde se necesita tracking del estado de cada solicitud.
- Flujos donde el servicio downstream tiene un esquema de correlación diferente al del requestor.
- Sistemas donde las políticas de timeout, retry y circuit breaker deben aplicarse de forma centralizada.
- Escenarios donde la respuesta necesita enriquecimiento con datos que el servicio no tiene.
Relación con Sistemas Distribuidos y Mensajería¶
Smart Proxy implementa el concepto de "conversation participant" de la teoría de messaging: un componente que participa en la conversación (no solo la observa) y puede influir en su resultado. En la arquitectura moderna de service mesh, los sidecars (Envoy) actúan como Smart Proxies para comunicación HTTP entre microservicios. Los API gateways (Kong, AWS API Gateway) son Smart Proxies para comunicación con clientes externos.
4. Problema que Resuelve¶
El Problema Antes del Patrón¶
Sin Smart Proxy, los flujos request-reply son directos entre requestor y servicio. Las consecuencias de esta comunicación directa incluyen:
- Opacidad: nadie sabe cuántas solicitudes están en vuelo, cuánto tiempo llevan, o cuál es la latencia típica.
- Timeout individual: cada requestor implementa su propia lógica de timeout, con diferentes umbrales y estrategias.
- Correlation incompatible: si el servicio downstream usa un ID de correlación diferente, el requestor debe mapear manualmente entre su ID y el del servicio.
- Respuestas sin contexto: la respuesta del servicio contiene solo lo que el servicio sabe, sin metadata de tracking ni información del contexto del requestor.
- Retry descentralizado: cada requestor implementa su propia lógica de retry, sin visibilidad centralizada de las solicitudes reintentadas.
Síntomas del Problema¶
- Los dashboards de monitoreo no pueden mostrar el estado de las solicitudes en vuelo porque no hay un punto centralizado de observación.
- Cada equipo implementa su propia lógica de timeout y retry, con diferentes umbrales y comportamientos.
- Las investigaciones de "solicitud perdida" requieren correlación manual entre logs del requestor y logs del servicio.
- Las respuestas del servicio externo no contienen el correlation ID del sistema interno, requiriendo tablas de mapeo mantenidas por cada requestor.
- Los SLAs de latencia de respuesta no pueden medirse porque no hay un punto centralizado de medición.
Impacto Operativo y Arquitectónico¶
- Visibilidad fragmentada: cada requestor tiene su propia visión parcial del estado de sus solicitudes.
- Políticas inconsistentes: timeouts, retries y circuit breakers se implementan de forma heterogénea.
- Debugging costoso: correlacionar solicitudes y respuestas a través de múltiples sistemas requiere esfuerzo manual.
- Escalabilidad de la gestión: cuando se añaden nuevos requestors, cada uno debe implementar su propia lógica de gestión de conversaciones.
Riesgos Si No Se Implementa Correctamente¶
- Memory leak de estado: si el Smart Proxy almacena estado de conversaciones pero no limpia las conversaciones completadas o expiradas, el estado crece indefinidamente.
- Single point of failure: si el proxy falla, todas las conversaciones en vuelo se pierden (solicitudes sin respuesta).
- Latencia añadida: cada solicitud y respuesta pasa por un hop adicional.
- Complejidad de correlación: si el proxy no mapea correctamente los correlation IDs, las respuestas llegan al requestor equivocado.
Ejemplos Reales¶
- Seguros: una aseguradora envía claims a múltiples reaseguradores. El Smart Proxy rastrear el estado de cada claim (enviado, en proceso, aprobado, rechazado), gestiona timeouts (si el reasegurador no responde en 48h) y enriquece la respuesta con metadata interna.
- Banca: un banco envía solicitudes de verificación de identidad a proveedores externos (Experian, Equifax). El Smart Proxy correlaciona las solicitudes (el proveedor usa su propio reference number, no el del banco), gestiona retries y mide SLA por proveedor.
- E-commerce: una plataforma envía solicitudes de envío a múltiples carriers (DHL, FedEx, UPS). El Smart Proxy rastrear el estado de cada solicitud, aplica circuit breaker por carrier, y enriquece la respuesta con datos de costo interno.
5. Contexto de Aplicación¶
Cuándo Usarlo¶
- Cuando se necesita tracking centralizado de solicitudes request-reply en vuelo.
- Cuando el servicio downstream usa un esquema de correlación diferente al del requestor.
- Cuando las respuestas necesitan enriquecimiento con datos que el servicio no posee.
- Cuando se requieren políticas centralizadas de timeout, retry y circuit breaker para flujos request-reply.
- Cuando se necesita medir SLAs de latencia de respuesta de forma centralizada.
- Cuando se integra con servicios externos que no implementan el esquema de correlación interno.
Cuándo No Usarlo¶
- Cuando el flujo request-reply es simple y directo, sin necesidad de tracking ni enriquecimiento.
- Cuando el servicio downstream soporta nativamente el correlation ID del requestor.
- Cuando la latencia añadida por el proxy es inaceptable.
- Cuando el flujo es fire-and-forget (no hay respuesta que rastrear).
- Cuando un API gateway existente ya proporciona las funcionalidades necesarias.
Precondiciones¶
- Los flujos request-reply están identificados y documentados.
- Existe un mecanismo de almacenamiento para el estado de las conversaciones en vuelo.
- El proxy puede interceptar tanto la solicitud como la respuesta (control del canal).
Restricciones¶
- El estado de conversaciones en vuelo debe persistirse si el proxy necesita sobrevivir a reinicios.
- El proxy añade latencia a cada solicitud y respuesta.
- El proxy debe escalar para manejar el volumen de conversaciones concurrentes.
Dependencias¶
- Almacenamiento de estado de conversaciones (in-memory cache, Redis, base de datos).
- Acceso a los canales de request y reply de las conversaciones que gestiona.
- Mecanismo de timeout para limpiar conversaciones expiradas.
Supuestos Arquitectónicos¶
- El proxy puede modificar la dirección de reply del mensaje para interceptar la respuesta.
- El volumen de conversaciones concurrentes es manejable por el almacenamiento de estado.
- Las conversaciones tienen un tiempo de vida finito (no permanecen en vuelo indefinidamente).
Tipo de Sistemas Donde Aparece con Más Frecuencia¶
- Sistemas de seguros (tracking de claims con reaseguradores).
- Sistemas bancarios (verificación de identidad con proveedores externos).
- Plataformas de e-commerce (gestión de envíos con múltiples carriers).
- Sistemas de integración B2B (gestión de solicitudes con partners).
- API gateways y service meshes (tracking de requests entre microservicios).
6. Fuerzas Arquitectónicas¶
Control Centralizado vs. Latencia Añadida¶
Smart Proxy centraliza el control de conversaciones request-reply, proporcionando visibilidad, policies y enriquecimiento. Pero cada mensaje (request y reply) atraviesa un hop adicional, añadiendo latencia. El balance está en si el valor del control justifica la latencia — en integraciones B2B con latencias de segundos, unos millisegundos de overhead son insignificantes; en flujos internos de baja latencia, pueden ser inaceptables.
Persistencia de Estado vs. Performance¶
El estado de conversaciones en vuelo debe almacenarse. In-memory es rápido pero se pierde con reinicios. Redis/bases de datos son durables pero más lentos. El balance depende de si la pérdida de estado es aceptable (reconexión recupera las conversaciones) o crítica (cada conversación perdida es un claim de seguros sin tracking).
Transparencia vs. Visibilidad¶
El Smart Proxy es transparente para requestor y servicio (no saben que existe). Pero esta transparencia puede dificultar el debugging si los desarrolladores no saben que hay un intermediario que modifica reply-to addresses y enriquece respuestas.
Simplicidad del Servicio vs. Complejidad del Proxy¶
Smart Proxy permite que los servicios sean simples (no necesitan implementar tracking, timeout ni enriquecimiento). Pero la complejidad se concentra en el proxy, que se convierte en un componente crítico con múltiples responsabilidades.
Aislamiento de Fallos vs. Single Point of Failure¶
Smart Proxy puede implementar circuit breaker y failover, aislando a los requestors de fallos del servicio. Pero el proxy mismo es un single point of failure — si falla, todas las conversaciones se interrumpen.
7. Estructura Conceptual del Patrón¶
Actores o Componentes Involucrados¶
- Requestor: el componente que envía la solicitud y espera la respuesta.
- Smart Proxy: el intermediario que intercepta, rastrea y enriquece la conversación.
- Conversation State Store: almacenamiento del estado de conversaciones en vuelo.
- Service: el servicio que procesa la solicitud y genera la respuesta.
- Request Channel: canal por donde viajan las solicitudes.
- Reply Channel: canal por donde viajan las respuestas.
Flujo Lógico¶
flowchart TD
A([Requestor]) -->|Solicitud + reply-to + correlation ID| B[Smart Proxy recibe solicitud]
B --> C[Genera proxy correlation ID]
C --> D[(Conversation State Store: guarda mapeo proxy-to-original)]
D --> E[Modifica reply-to y correlation ID al del proxy]
E -->|Reenvía solicitud modificada| F[Service procesa solicitud]
F -->|Respuesta al canal del proxy| G[Smart Proxy recibe respuesta]
G -->|Busca por proxy correlation ID| D
D -->|Recupera original corr ID + reply-to| H[Restaura correlation ID original]
H -->|Envía respuesta al canal original| I([Requestor recibe respuesta transparente])
G --> J[Elimina conversación del state store] Responsabilidades¶
| Componente | Responsabilidad |
|---|---|
| Requestor | Enviar solicitud y esperar respuesta (no sabe del proxy) |
| Smart Proxy | Interceptar, rastrear, enriquecer, correlacionar |
| Conversation State Store | Mantener estado de conversaciones en vuelo |
| Service | Procesar solicitud y retornar respuesta |
Interacciones¶
- Requestor → Smart Proxy: solicitud con reply-to y correlation ID del requestor.
- Smart Proxy → Service: solicitud con reply-to y correlation ID del proxy.
- Service → Smart Proxy: respuesta con correlation ID del proxy.
- Smart Proxy → Requestor: respuesta con correlation ID original restaurado.
Contratos Implícitos¶
- El servicio envía la respuesta al reply-to que recibió (el del proxy, no el del requestor).
- El proxy limpia las conversaciones completadas y expiradas del state store.
- El proxy no modifica el payload de la solicitud (solo metadata de routing).
Decisiones de Diseño Clave¶
- State store: ¿in-memory, Redis, base de datos? Depende del volumen y requisitos de durabilidad.
- Timeout handling: ¿el proxy genera un timeout response al requestor si el servicio no responde?
- Enriquecimiento: ¿qué datos añade el proxy a la respuesta? ¿Latencia, metadata del requestor, datos de auditoría?
- Failover: ¿qué pasa si el proxy se reinicia con conversaciones en vuelo? ¿Se pierden?
- Escalabilidad: ¿múltiples instancias del proxy con state store compartido (Redis)?
8. Ejemplo Arquitectónico Detallado¶
Dominio: Seguros — Tracking de Claims con Reaseguradores¶
Contexto del Negocio¶
Una compañía de seguros procesa 2,000 claims diarios. Para claims que superan un umbral de cobertura, la aseguradora debe consultar a uno o más reaseguradores para obtener aprobación de cobertura. Cada reasegurador tiene su propio sistema, su propio esquema de reference numbers y su propio SLA de respuesta (entre 1 hora y 48 horas).
Necesidad de Integración¶
La aseguradora necesita enviar solicitudes de aprobación a múltiples reaseguradores, rastrear el estado de cada solicitud, gestionar timeouts (si un reasegurador no responde en su SLA), enriquecer las respuestas con datos internos del claim, y correlacionar las respuestas del reasegurador (que usan sus propios reference numbers) con los claim IDs internos.
Sistemas Involucrados¶
- Claims Processing System: inicia la solicitud de aprobación.
- Smart Proxy: rastrea conversaciones con reaseguradores.
- Conversation State Store (Redis): estado de claims en vuelo.
- Reinsurer A Gateway: interfaz con Swiss Re (protocolo ACORD XML).
- Reinsurer B Gateway: interfaz con Munich Re (REST API).
- Reinsurer C Gateway: interfaz con Lloyd's (protocolo propietario).
- Claims Dashboard: muestra el estado de cada claim y sus solicitudes a reaseguradores.
Restricciones Técnicas¶
- Cada reasegurador usa su propio reference number (no el claim ID interno).
- Los tiempos de respuesta varían: Swiss Re (1-4h), Munich Re (2-24h), Lloyd's (4-48h).
- Si un reasegurador no responde dentro de su SLA, el proxy debe generar un timeout alert.
- El proxy debe enriquecer la respuesta del reasegurador con el claim ID interno, el monto solicitado y el nombre del asegurado.
- El Claims Dashboard debe poder consultar el estado de cada solicitud en tiempo real.
Diseño del Smart Proxy¶
Claims System
→ Queue: claims.reinsurance.requests
→ Smart Proxy
→ Conversation State Store (Redis)
→ Queue: reinsurer-a.requests (Swiss Re)
→ Queue: reinsurer-b.requests (Munich Re)
→ Queue: reinsurer-c.requests (Lloyd's)
Reinsurer A → Queue: reinsurer-a.replies → Smart Proxy
Reinsurer B → Queue: reinsurer-b.replies → Smart Proxy
Reinsurer C → Queue: reinsurer-c.replies → Smart Proxy
Smart Proxy → Queue: claims.reinsurance.responses → Claims System
Decisiones Arquitectónicas¶
- Redis como state store: cada conversación se almacena con TTL igual al SLA máximo del reasegurador + buffer. Redis proporciona baja latencia y expiración automática.
- Correlation mapping: el proxy genera un
proxy_referencepara cada reasegurador. Almacena el mapeo:{proxy_reference → claim_id, reinsurer, original_reply_to, timestamp}. - Timeout handling: un scheduled job verifica cada 5 minutos si hay conversaciones que excedieron su SLA. Si las hay, genera un timeout alert al Claims Dashboard y un timeout response al Claims System.
- Response enrichment: la respuesta del reasegurador (que solo contiene su reference number y la decisión) se enriquece con: claim_id, monto solicitado, nombre del asegurado, latencia de respuesta.
9. Desarrollo Paso a Paso del Ejemplo¶
Paso 1: Solicitud de Reinsurance¶
El Claims Processing System necesita aprobación de Swiss Re para el claim CLM-2026-04-07-1842 (siniestro de €500,000):
{
"claim_id": "CLM-2026-04-07-1842",
"correlation_id": "corr-claims-1842",
"reply_to": "claims.reinsurance.responses",
"payload": {
"insured": "Industrias Ibéricas S.A.",
"type": "property_damage",
"amount": 500000,
"currency": "EUR",
"target_reinsurer": "swiss-re"
}
}
Paso 2: Interceptación por el Smart Proxy¶
El Smart Proxy recibe la solicitud y crea el estado de la conversación:
// Almacenado en Redis con TTL=14400s (4h SLA de Swiss Re)
{
"key": "conv:proxy-ref-SR-20260407-001",
"value": {
"original_correlation_id": "corr-claims-1842",
"original_reply_to": "claims.reinsurance.responses",
"claim_id": "CLM-2026-04-07-1842",
"reinsurer": "swiss-re",
"sent_at": "2026-04-07T11:00:00.000Z",
"sla_deadline": "2026-04-07T15:00:00.000Z",
"status": "in_flight",
"enrichment_data": {
"insured": "Industrias Ibéricas S.A.",
"amount": 500000, "currency": "EUR"
}
}
}
Paso 3: Reenvío al Reasegurador¶
El Smart Proxy modifica la solicitud y la reenvía:
{
"proxy_reference": "proxy-ref-SR-20260407-001",
"reply_to": "smart-proxy.replies.swiss-re",
"payload": {
"cedant": "InsureCo Spain",
"type": "property_damage",
"amount": 500000,
"currency": "EUR",
"description": "Industrial facility fire damage"
}
}
Nota: el reply_to apunta al canal del proxy, no al del Claims System. Y el proxy_reference reemplaza al claim_id para la comunicación con Swiss Re.
Paso 4: Consulta de Estado (Dashboard)¶
Mientras espera la respuesta, el Claims Dashboard consulta el estado:
Respuesta:
{
"claim_id": "CLM-2026-04-07-1842",
"conversations": [{
"reinsurer": "swiss-re",
"status": "in_flight",
"sent_at": "2026-04-07T11:00:00.000Z",
"sla_deadline": "2026-04-07T15:00:00.000Z",
"elapsed_minutes": 45
}]
}
Paso 5: Recepción de la Respuesta del Reasegurador¶
Swiss Re responde después de 2 horas:
{
"sr_reference": "SR-EU-2026-78429",
"proxy_reference": "proxy-ref-SR-20260407-001",
"decision": "approved",
"approved_amount": 450000,
"conditions": "Subject to independent loss adjuster report"
}
Paso 6: Enriquecimiento y Reenvío¶
El Smart Proxy recibe la respuesta, busca el estado en Redis, enriquece y reenvía al Claims System:
{
"correlation_id": "corr-claims-1842",
"payload": {
"claim_id": "CLM-2026-04-07-1842",
"insured": "Industrias Ibéricas S.A.",
"reinsurer": "swiss-re",
"reinsurer_reference": "SR-EU-2026-78429",
"decision": "approved",
"requested_amount": 500000,
"approved_amount": 450000,
"currency": "EUR",
"conditions": "Subject to independent loss adjuster report",
"response_latency_minutes": 120,
"sla_met": true
}
}
La respuesta incluye datos que Swiss Re no tenía (claim_id, insured, requested_amount) y datos de tracking que el proxy calculó (response_latency_minutes, sla_met). El Claims System recibe la respuesta con su correlation_id original, como si hubiera hablado directamente con Swiss Re.
Paso 7: Limpieza¶
El proxy elimina la conversación de Redis y registra las métricas de SLA.
10. Diagrama Técnico del Patrón¶
Código Python con diagrams¶
Ver / Copiar código de los diagramas
from diagrams import Diagram, Cluster, Edge
from diagrams.onprem.queue import Kafka
from diagrams.onprem.compute import Server
from diagrams.onprem.database import PostgreSQL
from diagrams.onprem.inmemory import Redis
from diagrams.onprem.network import Internet
with Diagram("Smart Proxy - Reinsurance Claims", show=False, direction="LR"):
with Cluster("Claims System"):
claims = Server("Claims\nProcessing")
dashboard = Server("Claims\nDashboard")
with Cluster("Smart Proxy"):
proxy = Server("Smart\nProxy")
state = Redis("Conversation\nState")
with Cluster("Messaging"):
req_queue = Kafka("reinsurance\nrequests")
proxy_reply = Kafka("proxy\nreplies")
claims_reply = Kafka("claims\nresponses")
with Cluster("Reinsurers"):
swiss_re = Internet("Swiss Re")
munich_re = Internet("Munich Re")
lloyds = Internet("Lloyd's")
# Request flow
claims >> Edge(label="1. request") >> req_queue
req_queue >> Edge(label="2. intercept") >> proxy
proxy >> Edge(label="store state") >> state
proxy >> Edge(label="3. forward\n(modified reply-to)") >> swiss_re
proxy >> Edge(label="3. forward") >> munich_re
proxy >> Edge(label="3. forward") >> lloyds
# Reply flow
swiss_re >> Edge(label="4. reply\n(to proxy)") >> proxy_reply
munich_re >> Edge(label="4. reply") >> proxy_reply
proxy_reply >> Edge(label="5. receive") >> proxy
proxy >> Edge(label="6. enrich +\nforward") >> claims_reply
claims_reply >> Edge(label="7. response") >> claims
# Dashboard query
dashboard >> Edge(label="query state", style="dashed") >> state
from diagrams import Diagram, Cluster, Edge
from diagrams.aws.compute import Lambda
from diagrams.aws.database import ElasticacheForRedis
from diagrams.aws.integration import SQS
from diagrams.aws.network import APIGateway
with Diagram("Smart Proxy - Reinsurance Claims (AWS)", show=False, direction="LR"):
with Cluster("Claims System"):
claims = Lambda("Claims\nProcessing")
dashboard = Lambda("Claims\nDashboard")
with Cluster("Smart Proxy"):
proxy = Lambda("Smart Proxy\nLambda")
apigw = APIGateway("API Gateway\n(Proxy)")
state = ElasticacheForRedis("ElastiCache\nConversation State")
with Cluster("Messaging"):
req_queue = SQS("reinsurance\nrequests")
proxy_reply = SQS("proxy\nreplies")
claims_reply = SQS("claims\nresponses")
with Cluster("Reinsurers"):
swiss_re = APIGateway("Swiss Re\nAPI")
munich_re = APIGateway("Munich Re\nAPI")
lloyds = APIGateway("Lloyd's\nAPI")
# Request flow
claims >> Edge(label="1. request") >> req_queue
req_queue >> Edge(label="2. intercept") >> proxy
proxy >> Edge(label="store state") >> state
proxy >> Edge(label="3. forward\n(modified reply-to)") >> swiss_re
proxy >> Edge(label="3. forward") >> munich_re
proxy >> Edge(label="3. forward") >> lloyds
# Reply flow
swiss_re >> Edge(label="4. reply\n(to proxy)") >> proxy_reply
munich_re >> Edge(label="4. reply") >> proxy_reply
proxy_reply >> Edge(label="5. receive") >> proxy
proxy >> Edge(label="6. enrich +\nforward") >> claims_reply
claims_reply >> Edge(label="7. response") >> claims
# Dashboard query
dashboard >> Edge(label="query state", style="dashed") >> state
from diagrams import Diagram, Cluster, Edge
from diagrams.onprem.network import Internet
from diagrams.azure.compute import FunctionApps, ContainerApps
from diagrams.azure.database import CacheForRedis
from diagrams.azure.integration import ServiceBus, APIManagement
with Diagram("Smart Proxy - Reinsurance Claims (Azure)", show=False, direction="LR"):
with Cluster("Claims System"):
claims = ContainerApps("Claims\nContainer App")
dashboard = ContainerApps("Claims\nDashboard")
with Cluster("Smart Proxy"):
proxy = APIManagement("API Management\n(Smart Proxy)")
state = CacheForRedis("Azure Redis\nCache\n(Conversation State)")
with Cluster("Azure Service Bus"):
req_queue = ServiceBus("reinsurance-requests\nQueue")
proxy_reply = ServiceBus("proxy-replies\nQueue")
claims_reply = ServiceBus("claims-responses\nQueue")
with Cluster("Reinsurers"):
swiss_re = Internet("Swiss Re")
munich_re = Internet("Munich Re")
lloyds = Internet("Lloyd's")
# Request flow
claims >> Edge(label="1. request") >> req_queue
req_queue >> Edge(label="2. intercept") >> proxy
proxy >> Edge(label="store state") >> state
proxy >> Edge(label="3. forward\n(modified reply-to)") >> swiss_re
proxy >> Edge(label="3. forward") >> munich_re
proxy >> Edge(label="3. forward") >> lloyds
# Reply flow
swiss_re >> Edge(label="4. reply\n(to proxy)") >> proxy_reply
munich_re >> Edge(label="4. reply") >> proxy_reply
proxy_reply >> Edge(label="5. receive") >> proxy
proxy >> Edge(label="6. enrich +\nforward") >> claims_reply
claims_reply >> Edge(label="7. response") >> claims
# Dashboard query
dashboard >> Edge(label="query state", style="dashed") >> state
Explicación del Diagrama¶
El diagrama muestra los dos flujos del Smart Proxy:
- Flujo de request (izquierda a derecha): Claims System envía solicitud al proxy. El proxy almacena estado en Redis, modifica el reply-to y reenvía a los reaseguradores.
- Flujo de reply (derecha a izquierda): los reaseguradores responden al proxy (no al Claims System). El proxy enriquece la respuesta y la reenvía al Claims System con el correlation ID original.
- Consulta de estado (línea punteada): el Dashboard consulta Redis para mostrar el estado de las conversaciones en vuelo.
Correspondencia Patrón ↔ Diagrama¶
| Concepto del Patrón | Componente del Diagrama |
|---|---|
| Requestor | Claims Processing System |
| Smart Proxy | Smart Proxy server |
| Conversation State Store | Redis |
| Service | Reaseguradores (Swiss Re, Munich Re, Lloyd's) |
| Request Channel | reinsurance requests queue |
| Reply Channel | claims responses queue |
11. Beneficios¶
Impacto Técnico¶
- Correlación transparente: el proxy mapea entre el correlation scheme del requestor y el del servicio downstream sin que ninguno de los dos lo sepa.
- Tracking centralizado: todas las conversaciones en vuelo son visibles en un punto central, habilitando dashboards de estado en tiempo real.
- Timeout management: el proxy detecta conversaciones que exceden su SLA y genera timeout responses sin depender del requestor.
- Response enrichment: la respuesta se enriquece con datos del contexto del requestor que el servicio downstream no tiene.
Impacto Organizacional¶
- Visibilidad operacional: el equipo de operaciones puede ver el estado de todas las solicitudes en vuelo con reaseguradores en un solo dashboard.
- SLA measurement: la latencia de respuesta de cada reasegurador se mide de forma centralizada, alimentando decisiones de negocio.
- Simplificación del requestor: el Claims System no necesita implementar tracking, timeout ni mapping de correlación — el proxy lo hace.
Impacto Operacional¶
- Detección proactiva de problemas: si un reasegurador empieza a responder más lento, el proxy lo detecta antes de que las solicitudes empiecen a expirar.
- Retry centralizado: si una solicitud falla, el proxy puede reintentar sin que el requestor se entere.
- Audit trail: el proxy registra cada conversación (request, response, latencia, SLA compliance) para auditoría.
12. Desventajas y Riesgos¶
Complejidad Añadida¶
- Componente adicional: el proxy es un componente más que debe desplegarse, monitorearse y mantenerse.
- Estado que gestionar: el state store de conversaciones en vuelo requiere sizing, monitoring y limpieza.
- Latencia adicional: cada request y reply atraviesa un hop extra.
Riesgos de Mal Uso¶
- Proxy como orquestador: poner lógica de negocio en el proxy (decisiones de routing, transformaciones complejas), convirtiéndolo en un ESB disfrazado.
- Estado no limpiado: conversaciones en vuelo que nunca se completan ni expiran, consumiendo memoria y confundiendo los dashboards.
- Proxy como single point of failure: si el proxy falla y el state store es in-memory, todas las conversaciones en vuelo se pierden.
Sobreingeniería¶
- Proxy para flujos simples: añadir un Smart Proxy a un flujo request-reply directo que no necesita tracking, enriquecimiento ni mapping de correlación.
- Proxy para one-way: usar Smart Proxy en flujos fire-and-forget donde no hay respuesta que rastrear.
Anti-Patterns Relacionados¶
- Proxy as ESB: un Smart Proxy que acumula tantas responsabilidades (routing, transformación, orquestación, políticas) que se convierte en un ESB monolítico.
- Stale State: conversaciones en el state store que nunca se limpian, dando una visión incorrecta de la carga real.
13. Relación con Otros Patrones¶
Patrones Complementarios¶
- Request-Reply (Capítulo 4): Smart Proxy opera sobre flujos request-reply existentes.
- Correlation Identifier (Capítulo 4): el proxy mapea entre diferentes correlation identifiers.
- Wire Tap (este capítulo): el proxy puede actuar como wire tap de conversaciones request-reply.
- Control Bus (este capítulo): el proxy puede recibir comandos de control (cancel request, adjust timeout).
Patrones que Suelen Aparecer Juntos¶
- Smart Proxy + Correlation Identifier: el proxy mapea entre correlation schemes.
- Smart Proxy + Message Store: las conversaciones completadas se almacenan en un Message Store para auditoría.
- Smart Proxy + Content Enricher: el proxy enriquece respuestas con datos adicionales.
- Smart Proxy + Message History: el proxy añade su entrada al historial del mensaje.
Diferencias con Patrones Similares¶
- vs. Message Router: el Router dirige mensajes a destinos; el Smart Proxy intercepta conversaciones bidireccionales (request y reply).
- vs. Content Enricher: el Enricher añade datos a un mensaje en un punto del flujo; el Smart Proxy gestiona la conversación completa (request + reply + estado + timeout).
- vs. Wire Tap: el Wire Tap es un observador pasivo; el Smart Proxy es un participante activo que modifica headers, enriquece respuestas y genera timeout responses.
Encaje en un Flujo Mayor de Integración¶
Smart Proxy se posiciona en la frontera entre el sistema interno y servicios externos. Es el punto donde se aplican políticas de gestión de conversaciones (tracking, timeout, enrichment) antes de que las solicitudes crucen la frontera organizacional.
14. Relevancia Actual del Patrón¶
Evaluación: Relevancia Media¶
Argumentación¶
Smart Proxy tiene relevancia media porque muchas de sus responsabilidades han sido absorbidas por componentes de infraestructura moderna:
- API Gateways (Kong, AWS API Gateway, Azure API Management): gestionan tracking de requests, timeout, retry, rate limiting y enriquecimiento de forma nativa para comunicación HTTP.
- Service Mesh Sidecars (Envoy, Istio, Linkerd): interceptan comunicación entre microservicios de forma transparente, aplicando timeout, retry, circuit breaker y observabilidad sin código de aplicación.
- Orquestadores (Temporal, AWS Step Functions, Azure Durable Functions): gestionan conversaciones con estado de forma declarativa, con timeout y retry nativos.
Sin embargo, Smart Proxy sigue siendo relevante en escenarios específicos:
- Integración B2B con correlación incompatible: cuando los partners usan correlation schemes diferentes.
- Response enrichment: cuando las respuestas necesitan enriquecimiento con datos internos.
- Tracking de conversaciones asíncronas de largo plazo: claims de seguros, solicitudes de crédito, procesos regulatorios que duran horas o días.
Cómo Se Implementa Hoy¶
| Tecnología | Rol como Smart Proxy | Mecanismo |
|---|---|---|
| Kong / AWS API Gateway | Proxy HTTP con policies | Plugins, Lambda authorizers |
| Envoy / Istio | Service mesh sidecar | Transparent proxy con retry/timeout |
| Apache Camel | Integration framework | Routes con state management |
| Temporal / Step Functions | Workflow orchestrator | Activities con timeout y retry |
| Spring Integration | Messaging framework | Custom gateway con state store |
| Custom (Redis + consumers) | Ad-hoc implementation | Purpose-built para flujos específicos |
Qué Parte Sigue Siendo Esencial¶
- La gestión de correlación entre sistemas con diferentes ID schemes sigue requiriendo un proxy con estado.
- El tracking de conversaciones asíncronas de largo plazo no está resuelto por API gateways ni service meshes.
- El enriquecimiento de respuestas con datos internos requiere un componente que tenga acceso a ambos contextos.
15. Implementación en Arquitecturas Modernas¶
Spring Integration con Custom Smart Proxy¶
@Component
public class ReinsuranceSmartProxy {
private final RedisTemplate<String, ConversationState> stateStore;
@ServiceActivator(inputChannel = "reinsuranceRequests")
public Message<?> interceptRequest(Message<?> request) {
String proxyRef = generateProxyReference();
ConversationState state = ConversationState.builder()
.originalCorrelationId(request.getHeaders().get("correlationId", String.class))
.originalReplyTo(request.getHeaders().get("replyTo", String.class))
.claimId(request.getPayload().getClaimId())
.sentAt(Instant.now())
.build();
stateStore.opsForValue().set("conv:" + proxyRef, state, Duration.ofHours(48));
return MessageBuilder.fromMessage(request)
.setHeader("correlationId", proxyRef)
.setHeader("replyTo", "smart-proxy.replies")
.build();
}
@ServiceActivator(inputChannel = "proxyReplies")
public Message<?> interceptReply(Message<?> reply) {
String proxyRef = reply.getHeaders().get("correlationId", String.class);
ConversationState state = stateStore.opsForValue().get("conv:" + proxyRef);
stateStore.delete("conv:" + proxyRef);
Object enrichedPayload = enrichResponse(reply.getPayload(), state);
return MessageBuilder.withPayload(enrichedPayload)
.setHeader("correlationId", state.getOriginalCorrelationId())
.setHeader("replyTo", state.getOriginalReplyTo())
.build();
}
}
Envoy como Smart Proxy (Service Mesh)¶
# Envoy sidecar configuration - transparent proxy
static_resources:
clusters:
- name: reinsurer_swiss_re
connect_timeout: 5s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
circuit_breakers:
thresholds:
- max_connections: 100
max_pending_requests: 50
max_retries: 3
outlier_detection:
consecutive_5xx: 5
interval: 30s
load_assignment:
cluster_name: reinsurer_swiss_re
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: swiss-re-gateway.reinsurance
port_value: 443
listeners:
- name: reinsurance_listener
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
route_config:
virtual_hosts:
- routes:
- route:
cluster: reinsurer_swiss_re
timeout: 14400s # 4h SLA
retry_policy:
retry_on: "5xx,reset,connect-failure"
num_retries: 2
AWS Step Functions como Smart Proxy¶
{
"Comment": "Smart Proxy - Reinsurance Claim",
"StartAt": "StoreConversationState",
"States": {
"StoreConversationState": {
"Type": "Task",
"Resource": "arn:aws:states:::dynamodb:putItem",
"Parameters": {
"TableName": "conversation-state",
"Item": {
"proxy_ref": {"S.$": "$.proxy_reference"},
"claim_id": {"S.$": "$.claim_id"},
"sent_at": {"S.$": "$$.State.EnteredTime"}
}
},
"Next": "SendToReinsurer"
},
"SendToReinsurer": {
"Type": "Task",
"Resource": "arn:aws:states:::sqs:sendMessage.waitForTaskToken",
"Parameters": {
"QueueUrl": "https://sqs.../reinsurer-requests",
"MessageBody": {"claim.$": "$.payload", "taskToken.$": "$$.Task.Token"}
},
"TimeoutSeconds": 14400,
"Catch": [{
"ErrorEquals": ["States.Timeout"],
"Next": "HandleTimeout"
}],
"Next": "EnrichAndForward"
},
"EnrichAndForward": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:enrich-response",
"Next": "SendResponse"
},
"HandleTimeout": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:timeout-handler",
"Next": "SendResponse"
},
"SendResponse": {
"Type": "Task",
"Resource": "arn:aws:states:::sqs:sendMessage",
"End": true
}
}
}
16. Consideraciones de Gobierno y Operación¶
Observabilidad¶
- Dashboard de conversaciones en vuelo: número de conversaciones activas por reasegurador, tiempo medio en vuelo, conversaciones cerca de su SLA deadline.
- Métricas de SLA: porcentaje de respuestas dentro de SLA por reasegurador, distribución de latencia.
- Alertas de timeout: cuando conversaciones exceden su SLA sin respuesta.
- Alertas de state store: cuando el número de conversaciones en vuelo excede umbrales normales.
State Store Management¶
- Definir TTL por tipo de conversación (1h para verificaciones, 48h para claims).
- Monitorear el tamaño del state store y alertar ante crecimiento anómalo.
- Implementar cleanup de conversaciones huérfanas (estado en Redis pero respuesta perdida).
Seguridad¶
- El state store contiene datos de negocio sensibles (claim IDs, montos, nombres). Cifrar en reposo.
- Las solicitudes a reaseguradores externos deben usar TLS y autenticación mutua.
- El proxy no debe loguear payloads completos que contengan datos personales.
Disaster Recovery¶
- Si el proxy se reinicia, las conversaciones en vuelo en Redis sobreviven (asumiendo Redis persistente o cluster).
- Si Redis pierde datos, las conversaciones en vuelo se pierden. Los reaseguradores responderán pero el proxy no podrá correlacionar. Implementar un mecanismo de reconciliación.
Escalabilidad¶
- Múltiples instancias del proxy con Redis compartido.
- Particionamiento de conversaciones por reasegurador para procesamiento paralelo.
17. Errores Comunes¶
State Store Sin TTL¶
No configurar expiración de conversaciones en el state store. Cuando un reasegurador nunca responde (solicitud perdida), la conversación permanece en el store indefinidamente. Siempre configurar TTL con un margen sobre el SLA máximo.
Proxy Como ESB¶
Acumular responsabilidades en el Smart Proxy: routing por tipo de claim, transformación de formato, validación de negocio, cálculo de primas. El proxy debe limitarse a tracking, correlation mapping y enrichment. La lógica de negocio pertenece a los servicios.
No Gestionar el Reinicio del Proxy¶
Asumir que el proxy siempre está disponible. Si el proxy se reinicia con un state store in-memory, todas las conversaciones en vuelo se pierden. Usar un state store persistente (Redis con AOF/RDB, o una base de datos).
Correlation Mapping Incorrecto¶
Errores en el mapeo entre el proxy correlation ID y el original del requestor. Si la respuesta llega con un proxy_ref que no existe en el state store (por expiración o error), la respuesta se pierde. Implementar logging detallado y alertas para respuestas no correlacionables.
Timeout Sin Notificación¶
El proxy detecta que una conversación excedió su SLA pero no genera un timeout response al requestor. El requestor queda esperando indefinidamente. Siempre generar un timeout response explícito cuando se excede el SLA.
Enriquecimiento Excesivo¶
Añadir demasiados datos a la respuesta enriquecida, incluyendo datos que el requestor no necesita. El enriquecimiento debe ser específico y relevante — no un dump de toda la información disponible.
18. Conclusión Técnica¶
Smart Proxy es el patrón que introduce un intermediario con estado en flujos request-reply, habilitando tracking de conversaciones, mapping de correlación, gestión de timeouts y enriquecimiento de respuestas de forma transparente para requestor y servicio.
Cuándo aporta valor: en flujos request-reply con servicios externos que tienen esquemas de correlación incompatibles, SLAs de respuesta que deben monitorearse, y respuestas que necesitan enriquecimiento con datos internos. El valor es máximo en integraciones B2B de largo plazo (claims de seguros, solicitudes de crédito, procesos regulatorios) donde el tracking de cada conversación es un requisito operacional.
Cuándo evita problemas importantes: Smart Proxy evita la implementación descentralizada de tracking, timeout y correlation mapping en cada requestor, que resulta en comportamientos inconsistentes y debugging complejo. Centraliza estas responsabilidades en un punto observable y gestionable.
Cuándo no conviene adoptarlo: en flujos request-reply simples y directos donde el servicio soporta nativamente el correlation ID del requestor, no se necesita enriquecimiento, y los timeouts se gestionan adecuadamente en el requestor. También cuando un API gateway o service mesh ya proporciona las funcionalidades necesarias.
Recomendación para arquitectos: evalúe si las funcionalidades que necesita (tracking, correlation mapping, timeout, enrichment) están disponibles en su stack de infraestructura actual (API gateway, service mesh, orquestador). Si lo están, use la infraestructura existente en lugar de implementar un Smart Proxy custom. Si no lo están — particularmente en integraciones B2B asíncronas de largo plazo con correlation incompatible y necesidad de enrichment — un Smart Proxy custom es la solución apropiada. Asegúrese de que el state store es duradero (no in-memory) y que las conversaciones tienen TTL configurado.


