Invalid Message Channel¶
1. Nombre del Patrón¶
- Nombre oficial: Invalid Message Channel
- Categoría: Messaging Channels (Canales de Mensajería)
- Traducción contextual: Canal de Mensajes Inválidos
2. Resumen Ejecutivo¶
Invalid Message Channel es el patrón que define un canal dedicado para recibir mensajes que un consumidor no puede procesar porque son estructuralmente inválidos, semánticamente incomprensibles o de un tipo no reconocido. Cuando un consumidor recibe un mensaje que no puede parsear, que tiene un formato corrupto, que contiene un tipo desconocido o que viola las reglas de validación del dominio, en lugar de descartarlo silenciosamente o reintentar infinitamente, lo redirige a un canal específico de mensajes inválidos donde puede ser inspeccionado, diagnosticado y corregido.
El problema que resuelve es fundamental en cualquier arquitectura de mensajería: ¿qué hace un consumidor cuando recibe un mensaje que no entiende? Sin Invalid Message Channel, las opciones son todas malas: descartarlo (pérdida de datos), loguearlo y seguir (pérdida de datos con mejor auditoría), reintentar indefinidamente (bloqueo del consumidor), o fallar (detención del procesamiento). Invalid Message Channel ofrece una quinta opción superior: preservar el mensaje problemático en un canal dedicado donde un operador o un sistema automatizado puede analizarlo y tomar acción correctiva.
Es crítico distinguir este patrón de Dead Letter Channel. Invalid Message Channel maneja mensajes que el consumidor rechaza activamente porque no puede comprenderlos (problema de contenido). Dead Letter Channel maneja mensajes que el sistema de mensajería no puede entregar después de agotar los reintentos (problema de infraestructura o procesamiento). La causa es diferente: contenido inválido vs. entrega fallida. El tratamiento también difiere: los mensajes inválidos típicamente requieren corrección manual del contenido o del productor; los mensajes dead-lettered típicamente requieren corrección del consumidor o de la infraestructura.
3. Definición Detallada¶
Propósito¶
Invalid Message Channel establece un destino seguro y monitoreable para mensajes que un consumidor determina que son inválidos. Su propósito es triple: (1) evitar que mensajes inválidos bloqueen el procesamiento de mensajes válidos, (2) preservar los mensajes inválidos para diagnóstico y posible reprocesamiento, y (3) proporcionar visibilidad operacional sobre la tasa y naturaleza de los mensajes inválidos.
Lógica Arquitectónica¶
El patrón introduce un flujo alternativo explícito en el procesamiento de mensajes. En lugar de un flujo lineal (recibir → procesar → confirmar), se establece un flujo con bifurcación (recibir → validar → si válido: procesar y confirmar → si inválido: enviar a Invalid Message Channel y confirmar en el canal original).
Esta bifurcación tiene consecuencias arquitectónicas importantes:
- Resiliencia del consumidor: un mensaje inválido no detiene ni bloquea al consumidor. El flujo principal continúa procesando mensajes válidos sin interrupción.
- Preservación de evidencia: el mensaje inválido se almacena íntegramente (headers, payload, metadata) en el canal de inválidos, permitiendo diagnóstico posterior.
- Separación de responsabilidades: el consumidor se enfoca en procesar mensajes válidos. El equipo de operaciones o un sistema de corrección se enfoca en los mensajes inválidos.
- Feedback loop: la tasa de mensajes inválidos es un indicador de calidad del productor. Un pico de mensajes inválidos señala un bug en el productor o un cambio de esquema no coordinado.
Principio de Diseño Subyacente¶
El principio es fail-safe con preservación: cuando un componente no puede procesar un dato, lo preserva en un canal seguro en lugar de destruirlo o bloquearse. Es el equivalente en messaging del manejo de excepciones en programación: capturar la excepción, registrar el contexto y continuar la ejecución normal.
Problema Estructural que Resuelve¶
En un sistema de mensajería sin Invalid Message Channel, los mensajes inválidos producen uno de estos escenarios:
- Infinite retry loop: el consumidor reintenta el mensaje indefinidamente porque el error de validación es determinista (siempre fallará). Esto bloquea la partición o el canal completo.
- Silent discard: el consumidor descarta el mensaje y avanza el offset. El mensaje se pierde sin registro. El productor no se entera del problema.
- Consumer crash: el consumidor falla ante el mensaje inválido, se reinicia, vuelve a leer el mismo mensaje, vuelve a fallar — un crash loop.
- Manual intervention required: un operador debe intervenir para saltar el mensaje, lo cual no escala y no es sostenible.
Invalid Message Channel elimina estos escenarios proporcionando un destino automático para mensajes que no pasan la validación.
Contexto en el que Emerge¶
Invalid Message Channel emerge cuando un sistema de mensajería madura y se enfrenta a la realidad de datos imperfectos. En un sistema nuevo con un solo productor controlado, los mensajes inválidos son raros. Pero cuando múltiples productores (algunos legacy, algunos de terceros) envían mensajes a los mismos canales, la probabilidad de mensajes malformados, con campos faltantes, con tipos incorrectos o con codificación corrupta aumenta significativamente.
Relación con Sistemas Distribuidos y Mensajería¶
En la teoría de sistemas distribuidos, Invalid Message Channel implementa el patrón de error isolation. El principio es que un error en un dato individual no debe afectar al procesamiento de otros datos. En el contexto de messaging, un mensaje inválido no debe afectar al procesamiento de mensajes válidos que están en el mismo canal.
4. Problema que Resuelve¶
El Problema Antes del Patrón¶
Sin Invalid Message Channel, los consumidores enfrentan un dilema cuando reciben un mensaje incomprensible:
- ¿Reintentar? Si el problema es determinista (formato corrupto, campo faltante, tipo desconocido), reintentar no lo resolverá nunca. El mensaje se reintenta infinitamente, bloqueando el procesamiento.
- ¿Descartar? Si el mensaje contiene datos de negocio importantes (un resultado de laboratorio, una transacción financiera, un pedido), descartarlo puede tener consecuencias graves.
- ¿Parar? Detener el consumidor hasta que un operador resuelva el problema es inaceptable en sistemas 24/7.
- ¿Loguear y continuar? Mejor que descartar silenciosamente, pero un log se pierde entre miles de líneas. No hay mecanismo de seguimiento, corrección ni reprocesamiento.
Síntomas del Problema¶
- Consumer groups con consumer lag creciente sin razón aparente (un mensaje inválido bloquea una partición en un retry loop).
- Alertas de "consumer restarting" frecuentes (crash loops por mensajes inválidos).
- Discrepancias de datos entre sistemas: el productor envió 1,000 mensajes pero el consumidor solo procesó 997. Los 3 faltantes fueron descartados silenciosamente.
- Tickets de soporte diciendo "el sistema no procesó mi pedido/resultado/transacción" que requieren investigación manual en logs.
Impacto Operativo y Arquitectónico¶
Sin manejo explícito de mensajes inválidos:
- Degradación progresiva: cada mensaje inválido que bloquea una partición reduce la capacidad de procesamiento. Con el tiempo, múltiples particiones bloqueadas degradan significativamente el throughput.
- Pérdida de datos silenciosa: mensajes descartados sin registro constituyen pérdida de datos. En dominios regulados (salud, finanzas), esto puede tener consecuencias legales.
- Falta de feedback al productor: sin un canal de inválidos monitoreable, el productor no se entera de que está generando mensajes defectuosos. El bug persiste.
- Operaciones manuales no escalables: resolver mensajes inválidos caso por caso con intervención manual no escala cuando el volumen crece.
Riesgos Si No Se Implementa Correctamente¶
- Poison pill: un mensaje inválido que ningún consumidor puede procesar circula indefinidamente, consumiendo recursos y bloqueando procesamiento.
- Cascade failure: un consumidor que falla ante un mensaje inválido y se reinicia puede causar rebalanceo del consumer group, afectando a otros consumidores del grupo.
- Data loss compliance violations: en dominios regulados, la pérdida silenciosa de mensajes puede violar regulaciones (HIPAA en salud, PCI-DSS en pagos).
Ejemplos Reales¶
- Healthcare: un Hospital Information System (HIS) envía resultados de laboratorio en formato HL7 v2.x a un Electronic Medical Record (EMR). Un parser del HIS genera un mensaje HL7 malformado (segmento OBX sin campo OBX-3 obligatorio). Sin Invalid Message Channel, el EMR descarta el resultado y el médico no ve la analítica del paciente. Con Invalid Message Channel, el mensaje malformado se preserva, se genera una alerta, y un operador del HIS corrige y reenvía el resultado.
- E-commerce: un marketplace recibe pedidos de 500 sellers. Un seller envía un pedido con un campo
pricecomo string ("29.99 EUR") en lugar de un número. El consumidor no puede parsear el precio. Sin Invalid Message Channel, el pedido se pierde. Con Invalid Message Channel, el pedido se preserva y se notifica al seller para que corrija su integración. - Telecomunicaciones: un sistema de mediación procesa CDRs de 200 elementos de red de diferentes fabricantes. Un elemento de red actualiza su firmware y cambia el formato de los CDRs sin previo aviso. Los CDRs con el nuevo formato son inválidos para el parser actual. Con Invalid Message Channel, los CDRs inválidos se preservan mientras se actualiza el parser.
5. Contexto de Aplicación¶
Cuándo Usarlo¶
- Siempre que un consumidor procese mensajes de fuentes no completamente controladas (productores de terceros, sistemas legacy, integraciones externas).
- Cuando los mensajes pueden tener errores de formato, estructura o contenido que el consumidor no puede resolver por sí mismo.
- En dominios donde la pérdida de datos es inaceptable (salud, finanzas, regulación).
- Cuando se necesita un mecanismo de feedback sobre la calidad de los datos producidos.
- Como complemento de Dead Letter Channel: Invalid Message Channel para errores de contenido; Dead Letter Channel para errores de entrega.
Cuándo No Usarlo¶
- Si todos los productores están completamente controlados y validados antes de producir (aunque esto es raro en la práctica).
- Si los mensajes inválidos son genuinamente irrecuperables y no tienen valor de diagnóstico (por ejemplo, telemetría corrupta de sensores desechables). Incluso en este caso, monitorear la tasa de mensajes inválidos tiene valor.
- Si el volumen de mensajes inválidos esperado es tan alto que el canal de inválidos se convierte en un problema mayor que el original. En este caso, el problema raíz es la calidad del productor, no el manejo de errores.
Precondiciones¶
- Existe un canal principal donde el consumidor recibe mensajes.
- El consumidor puede distinguir entre un mensaje válido y un mensaje inválido (tiene lógica de validación).
- Existe un canal de inválidos creado y configurado en el broker.
- Existe un proceso (manual o automatizado) para revisar y actuar sobre los mensajes inválidos.
Restricciones¶
- El canal de inválidos consume recursos adicionales (storage, monitoreo).
- Los mensajes en el canal de inválidos necesitan contexto suficiente para diagnóstico (no basta con el payload; se necesitan headers, timestamps, razón del rechazo, canal de origen).
- Sin un proceso de revisión, el canal de inválidos se convierte en un "vertedero" de mensajes que nadie examina.
Dependencias¶
- Canal principal donde el consumidor recibe mensajes.
- Canal de inválidos configurado y monitoreable.
- Lógica de validación en el consumidor que determine si un mensaje es válido o inválido.
- Proceso operacional de revisión y corrección de mensajes inválidos.
Supuestos Arquitectónicos¶
- El consumidor puede detectar mensajes inválidos sin efectos secundarios (la validación no modifica estado).
- El envío al canal de inválidos no falla (si falla, se necesita un fallback adicional).
- Los mensajes inválidos tienen valor de diagnóstico y no deben descartarse.
6. Fuerzas Arquitectónicas¶
Resiliencia vs. Complejidad¶
Invalid Message Channel aumenta significativamente la resiliencia: un mensaje inválido no detiene al consumidor. Pero añade complejidad: el consumidor necesita lógica de validación, lógica de routing al canal de inválidos, y enriquecimiento del mensaje con metadata de diagnóstico.
Preservación vs. Costo¶
Preservar todos los mensajes inválidos proporciona máxima capacidad de diagnóstico y recuperación. Pero el storage tiene costo. En sistemas de alto volumen con productores de baja calidad, el canal de inválidos puede crecer rápidamente. La retención del canal de inválidos debe dimensionarse según la capacidad de revisión y corrección.
Automatización vs. Intervención Humana¶
Algunos mensajes inválidos pueden corregirse automáticamente (formato de fecha incorrecto, encoding mal detectado). Otros requieren intervención humana (campo obligatorio faltante que no puede inferirse, tipo de mensaje completamente desconocido). El diseño del canal de inválidos debe soportar ambos flujos.
Feedback vs. Acoplamiento¶
Notificar al productor cuando sus mensajes son inválidos crea un feedback loop valioso. Pero también introduce acoplamiento: el consumidor necesita saber quién es el productor para notificarlo. Alternativa: publicar métricas de invalidez por canal que el productor consulte sin acoplamiento directo.
Granularidad de Validación vs. Performance¶
Validación exhaustiva (estructura, tipos, rangos, reglas de negocio, referencias cruzadas) detecta más mensajes inválidos pero consume más CPU y aumenta la latencia. Validación mínima (solo estructura básica) es más rápida pero deja pasar mensajes con errores semánticos. El nivel de validación debe ajustarse al dominio y al SLA.
Inmediatez vs. Batch¶
¿Los mensajes inválidos deben revisarse en tiempo real (alerta inmediata por cada uno) o en batch (reporte diario de mensajes inválidos)? Depende de la criticidad del dominio: un resultado de laboratorio inválido requiere atención inmediata; una métrica de telemetría inválida puede esperar a un reporte diario.
7. Estructura Conceptual del Patrón¶
Actores o Componentes Involucrados¶
- Productor: envía mensajes al canal principal (puede ser la fuente del error).
- Canal Principal: canal donde el consumidor recibe mensajes para procesar.
- Consumidor con Validación: consumidor que valida cada mensaje antes de procesarlo.
- Invalid Message Channel: canal dedicado que recibe mensajes rechazados por el consumidor.
- Error Metadata: información adicional que el consumidor agrega al mensaje inválido (razón del rechazo, timestamp, consumer ID, canal de origen).
- Operador / Sistema de Corrección: persona o sistema que revisa, diagnostica y actúa sobre los mensajes inválidos.
Flujo Lógico¶
flowchart TD
A([Productor]) -->|Envía mensaje| B[(Canal Principal)]
B --> C[Consumidor: Recibe mensaje]
C --> D{Validación}
D -->|Deserialización OK<br>Estructura OK<br>Semántica OK| E[Procesa normalmente]
E --> F[ACK en canal principal]
D -->|Validación falla| G[Construye mensaje de error<br>payload + headers + razón rechazo]
G --> H[(Invalid Message Channel)]
G --> I[ACK en canal principal]
H --> J[Operador: Monitorea y diagnostica]
J --> K{Acción correctiva}
K -->|Corrige y reenvía| B
K -->|Notifica al productor| L[Productor corrige código]
K -->|Actualiza validación| M[Ajusta lógica de validación] Responsabilidades¶
| Componente | Responsabilidad |
|---|---|
| Productor | Producir mensajes (idealmente válidos, pero no siempre bajo control del consumidor) |
| Canal Principal | Transportar mensajes hacia el consumidor |
| Consumidor | Validar mensajes, procesar los válidos, redirigir los inválidos |
| Invalid Message Channel | Almacenar mensajes inválidos con metadata de diagnóstico |
| Operador/Sistema | Revisar mensajes inválidos, diagnosticar causa raíz, tomar acción correctiva |
Interacciones¶
- Canal Principal → Consumidor: entrega del mensaje para procesamiento.
- Consumidor → Invalid Message Channel: redirección del mensaje inválido con metadata de error.
- Invalid Message Channel → Operador: notificación (alerta) o consulta (pull) de mensajes inválidos.
- Operador → Canal Principal (opcional): reenvío del mensaje corregido para reprocesamiento.
- Operador → Productor (opcional): notificación del error para corrección en origen.
Decisiones de Diseño Clave¶
- Qué constituye un mensaje "inválido": ¿solo errores de formato/deserialización? ¿También errores de validación de negocio? La definición debe ser explícita.
- Qué metadata incluir: el mensaje en el canal de inválidos debe contener suficiente información para diagnosticar sin acceso al canal principal (payload original, headers, razón, timestamp, consumer).
- Naming del canal: convención como
{canal-principal}.invalido{dominio}.invalid-messages. - Retención: cuánto tiempo se retienen los mensajes inválidos (depende del SLA de resolución).
- Proceso de corrección: ¿manual (operador revisa), semi-automatizado (reglas de corrección) o automatizado (auto-fix para errores conocidos)?
8. Ejemplo Arquitectónico Detallado¶
Dominio: Healthcare — Integración de Mensajes HL7¶
Contexto del Negocio¶
Un hospital de tercer nivel opera un ecosistema de sistemas clínicos que intercambian información mediante mensajes HL7 v2.x:
- Laboratory Information System (LIS): genera resultados de laboratorio (mensajes ORU^R01).
- Radiology Information System (RIS): genera informes de radiología (mensajes ORU^R01 con segmentos específicos).
- Pharmacy System: genera dispensaciones de medicamentos (mensajes RDE^O11).
- ADT System: genera admisiones, traslados y altas (mensajes ADT^A01, ADT^A02, ADT^A03).
- Electronic Medical Record (EMR): consume todos estos mensajes para construir la historia clínica electrónica del paciente.
Necesidad de Integración¶
El EMR recibe aproximadamente 15,000 mensajes HL7 diarios de cuatro sistemas fuente diferentes, cada uno con su propia versión de HL7, su propia implementación y sus propias peculiaridades. Los mensajes pueden ser inválidos por múltiples razones:
- Formato HL7 malformado: segmentos sin delimitador correcto, campos con encoding incorrecto.
- Campos obligatorios faltantes: un OBX sin el campo OBX-3 (Observation Identifier) que identifica qué tipo de resultado es.
- Tipos de mensaje desconocidos: un sistema fuente envía un tipo de mensaje HL7 que el EMR no está configurado para procesar (por ejemplo, MDM^T02 de documentos).
- Valores fuera de rango: un resultado de laboratorio con un valor numérico que excede el rango fisiológicamente posible (indicando error de medición o transmisión).
- Referencias inválidas: un resultado de laboratorio referencia a un paciente que no existe en el ADT (Patient ID no encontrado).
Sistemas Involucrados¶
- Integration Engine (Mirth Connect): recibe mensajes HL7 de los sistemas fuente, los valida y los enruta.
- Kafka Cluster: plataforma de messaging para los canales de integración.
- EMR Consumer: servicio que consume mensajes HL7 validados e integra los datos en el EMR.
- Invalid Message Channel: canal dedicado para mensajes HL7 que no pasan validación.
- Invalid Message Dashboard: aplicación web donde el equipo de integración revisa y gestiona los mensajes inválidos.
- Notification Service: servicio que alerta al equipo de integración cuando hay mensajes inválidos críticos.
Diseño de Canales¶
| Canal (Kafka Topic) | Propósito | Productor | Consumidor |
|---|---|---|---|
clinical.hl7.results | Resultados de lab y radiología validados | Integration Engine | EMR Consumer |
clinical.hl7.pharmacy | Dispensaciones validadas | Integration Engine | EMR Consumer |
clinical.hl7.adt | Admisiones, traslados, altas validados | Integration Engine | EMR Consumer |
clinical.hl7.invalid | Mensajes HL7 que no pasan validación | Integration Engine / EMR Consumer | Invalid Message Dashboard |
Decisiones Arquitectónicas¶
-
Validación en dos niveles: el Integration Engine realiza validación estructural (formato HL7 correcto, segmentos requeridos presentes). El EMR Consumer realiza validación semántica (Patient ID existe, valores en rango). Ambos niveles envían rechazos al mismo Invalid Message Channel.
-
Mensaje de error enriquecido: cada mensaje en el canal de inválidos incluye el payload HL7 original completo, headers de Kafka con la razón del rechazo, el nivel de validación que falló, el sistema fuente y el timestamp.
-
Clasificación de severidad: los mensajes inválidos se clasifican en CRITICAL (resultado de laboratorio de paciente en UCI), HIGH (resultado de laboratorio ordinario), MEDIUM (dispensación farmacéutica), LOW (información administrativa). La severidad determina el SLA de resolución.
-
Retención de 90 días: los mensajes inválidos se retienen 90 días para cumplir con requisitos de auditoría de la Joint Commission y regulación HIPAA.
Riesgos y Mitigaciones¶
| Riesgo | Mitigación |
|---|---|
| Resultado crítico perdido en canal de inválidos | Alerta inmediata (PagerDuty) para mensajes con severidad CRITICAL |
| Volumen excesivo de inválidos satura al equipo | Dashboard con filtros, agrupación por tipo de error y priorización automática |
| Mensaje corregido y reenviado sin eliminar del canal de inválidos | Workflow en dashboard que marca el mensaje como "resuelto" y registra la acción |
| Productor no se entera de que genera mensajes inválidos | Reporte semanal automático por sistema fuente con tasa de invalidez |
| Canal de inválidos sin monitoreo se convierte en vertedero | Alerta si el canal de inválidos tiene mensajes sin revisar > 24 horas |
9. Desarrollo Paso a Paso del Ejemplo¶
Paso 1: Generación de Mensaje HL7 en el LIS¶
El laboratorio del hospital completa un análisis de hemograma para la paciente María García (MRN: PAT-2026-38291), ingresada en la UCI con sospecha de sepsis. El LIS genera un mensaje HL7 ORU^R01:
MSH|^~\&|LAB_SYSTEM|HOSPITAL|EMR|HOSPITAL|20260407143200||ORU^R01|MSG-LAB-9928|P|2.5.1
PID|||PAT-2026-38291||GARCIA^MARIA||19680315|F
OBR|1|ORD-8827|RES-8827|CBC^HEMOGRAMA^L|||20260407140000
OBX|1|NM|WBC^Leucocitos^L||18.5|10*3/uL|4.5-11.0|H|||F
OBX|2|NM|HGB^Hemoglobina^L||9.2|g/dL|12.0-16.0|L|||F
OBX|3|NM||^Plaquetas^L||185|10*3/uL|150-400|N|||F
El tercer segmento OBX tiene un error: el campo OBX-3 (Observation Identifier) está vacío (falta el código PLT). El campo OBX-3 es obligatorio según el estándar HL7.
Paso 2: Recepción y Validación Estructural¶
El Integration Engine (Mirth Connect) recibe el mensaje HL7 y ejecuta validación estructural:
- Valida la estructura MSH (correcto).
- Valida PID con Patient ID (presente).
- Valida cada segmento OBR y OBX.
- Detecta: OBX-3 del tercer segmento está vacío. OBX-3 es obligatorio según el perfil HL7 configurado.
La validación falla. El Integration Engine genera un mensaje de error enriquecido.
Paso 3: Envío al Invalid Message Channel¶
El Integration Engine produce un mensaje en clinical.hl7.invalid:
{
"original_message": "MSH|^~\\&|LAB_SYSTEM|HOSPITAL|EMR|HOSPITAL|20260407143200||ORU^R01|MSG-LAB-9928|P|2.5.1\rPID|||PAT-2026-38291||GARCIA^MARIA||19680315|F\rOBR|1|ORD-8827|RES-8827|CBC^HEMOGRAMA^L|||20260407140000\rOBX|1|NM|WBC^Leucocitos^L||18.5|10*3/uL|4.5-11.0|H|||F\rOBX|2|NM|HGB^Hemoglobina^L||9.2|g/dL|12.0-16.0|L|||F\rOBX|3|NM||^Plaquetas^L||185|10*3/uL|150-400|N|||F",
"error_details": {
"validation_level": "STRUCTURAL",
"errors": [
{
"segment": "OBX",
"segment_index": 3,
"field": "OBX-3",
"field_name": "Observation Identifier",
"error_type": "REQUIRED_FIELD_EMPTY",
"message": "OBX-3 (Observation Identifier) is required but empty in OBX segment #3"
}
]
},
"source_system": "LAB_SYSTEM",
"message_type": "ORU^R01",
"message_control_id": "MSG-LAB-9928",
"patient_id": "PAT-2026-38291",
"severity": "CRITICAL",
"rejected_by": "integration-engine-01",
"rejected_at": "2026-04-07T14:32:05Z",
"original_channel": "clinical.hl7.results",
"rejection_reason_summary": "Structural validation failed: OBX-3 empty in segment 3"
}
Nótese que la severidad es CRITICAL porque: (1) es un resultado de laboratorio, (2) el paciente está en UCI (inferido del contexto de la orden).
Paso 4: Alerta Inmediata¶
El Notification Service consume de clinical.hl7.invalid, detecta severidad CRITICAL y:
- Envía una alerta a PagerDuty al equipo de integración del hospital.
- Envía una notificación al dashboard del equipo de laboratorio.
- Registra el incidente en el sistema de tickets con prioridad P1.
Tiempo desde generación del mensaje hasta alerta: menos de 30 segundos.
Paso 5: Diagnóstico en el Dashboard¶
El analista de integración abre el Invalid Message Dashboard:
- Ve el mensaje inválido con todos los detalles: payload original, error específico (OBX-3 vacío en segmento 3), sistema fuente (LAB_SYSTEM), paciente (PAT-2026-38291).
- Identifica que el error es un bug en el parser del LIS: cuando el código del analito es "PLT" (plaquetas), el mapper no lo incluye en OBX-3.
- Contacta al equipo del LIS para corregir el bug.
Paso 6: Corrección y Reprocesamiento¶
Mientras el LIS corrige el bug:
- El analista corrige manualmente el mensaje HL7, añadiendo
PLTen OBX-3. - Reenvía el mensaje corregido al canal
clinical.hl7.results. - El EMR Consumer procesa el resultado de plaquetas de la paciente.
- Marca el mensaje como "resuelto" en el dashboard.
El resultado de laboratorio llega al EMR con un retraso de 45 minutos (en lugar de los 30 segundos normales), pero no se pierde. El médico de la UCI tiene acceso al hemograma completo.
Paso 7: Corrección en Origen¶
El equipo del LIS corrige el bug en el parser y despliega la corrección. El analista de integración monitorea el canal de inválidos los días siguientes y confirma que no hay más mensajes con el mismo error del LIS.
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.monitoring import Grafana
from diagrams.onprem.client import User
from diagrams.saas.alerting import Pagerduty
with Diagram("Invalid Message Channel - Healthcare HL7", show=False, direction="LR"):
with Cluster("Sistemas Clínicos Fuente"):
lis = Server("LIS\n(Laboratorio)")
ris = Server("RIS\n(Radiología)")
pharmacy = Server("Pharmacy\nSystem")
adt = Server("ADT\nSystem")
with Cluster("Integration Layer"):
engine = Server("Integration\nEngine\n(Mirth Connect)")
with Cluster("Kafka - Canales de Integración"):
results_ch = Kafka("clinical.hl7.results\n(mensajes válidos)")
pharmacy_ch = Kafka("clinical.hl7.pharmacy\n(mensajes válidos)")
adt_ch = Kafka("clinical.hl7.adt\n(mensajes válidos)")
invalid_ch = Kafka("clinical.hl7.invalid\n(INVALID MESSAGE\nCHANNEL)")
with Cluster("Consumidores"):
emr = Server("EMR\nConsumer")
invalid_dash = Server("Invalid Message\nDashboard")
with Cluster("Almacenamiento"):
emr_db = PostgreSQL("EMR\nDatabase")
invalid_db = PostgreSQL("Invalid\nMessages DB")
pager = Pagerduty("PagerDuty\nAlerts")
operator = User("Integration\nAnalyst")
monitoring = Grafana("Invalid Rate\nMonitoring")
# Fuentes al Integration Engine
lis >> engine
ris >> engine
pharmacy >> engine
adt >> engine
# Flujo válido
engine >> Edge(color="green", label="valid") >> results_ch
engine >> Edge(color="green", label="valid") >> pharmacy_ch
engine >> Edge(color="green", label="valid") >> adt_ch
# Flujo inválido
engine >> Edge(color="red", style="bold", label="invalid") >> invalid_ch
# Consumo válido
results_ch >> emr >> emr_db
pharmacy_ch >> emr
adt_ch >> emr
# Consumo de inválidos
invalid_ch >> invalid_dash >> invalid_db
invalid_ch >> Edge(style="dashed", color="red") >> pager
invalid_dash >> operator
operator >> Edge(style="dashed", label="corrected\nmessage") >> results_ch
# Monitoreo
invalid_ch >> Edge(style="dotted") >> monitoring
from diagrams import Diagram, Cluster, Edge
from diagrams.onprem.client import User
from diagrams.saas.alerting import Pagerduty
from diagrams.aws.compute import ECS, Lambda
from diagrams.aws.database import Dynamodb, RDS
from diagrams.aws.integration import SQS
from diagrams.aws.management import Cloudwatch
with Diagram("Invalid Message Channel - Healthcare HL7 (AWS)", show=False, direction="LR"):
with Cluster("Sistemas Clínicos Fuente"):
lis = ECS("LIS\n(Laboratorio)")
ris = ECS("RIS\n(Radiología)")
pharmacy = ECS("Pharmacy\nSystem")
adt = ECS("ADT\nSystem")
with Cluster("Integration Layer"):
engine = ECS("Integration\nEngine\n(Fargate)")
with Cluster("SQS Queues"):
results_ch = SQS("clinical.hl7.results\n(SQS - válidos)")
pharmacy_ch = SQS("clinical.hl7.pharmacy\n(SQS - válidos)")
adt_ch = SQS("clinical.hl7.adt\n(SQS - válidos)")
invalid_ch = SQS("clinical.hl7.invalid\n(SQS DLQ -\nINVALID MESSAGES)")
with Cluster("Consumidores"):
emr = Lambda("EMR\nConsumer\n(Lambda)")
invalid_dash = Lambda("Invalid Message\nDashboard\n(Lambda)")
with Cluster("Almacenamiento"):
emr_db = RDS("EMR\nDatabase\n(Aurora)")
invalid_db = Dynamodb("Invalid\nMessages\n(DynamoDB)")
pager = Pagerduty("PagerDuty\nAlerts")
operator = User("Integration\nAnalyst")
monitoring = Cloudwatch("CloudWatch\nAlarm\n(Invalid Rate)")
# Fuentes al Integration Engine
lis >> engine
ris >> engine
pharmacy >> engine
adt >> engine
# Flujo válido
engine >> Edge(color="green", label="valid") >> results_ch
engine >> Edge(color="green", label="valid") >> pharmacy_ch
engine >> Edge(color="green", label="valid") >> adt_ch
# Flujo inválido (SQS DLQ)
engine >> Edge(color="red", style="bold", label="invalid") >> invalid_ch
# Consumo válido (SQS → Lambda)
results_ch >> emr >> emr_db
pharmacy_ch >> emr
adt_ch >> emr
# Consumo de inválidos
invalid_ch >> invalid_dash >> invalid_db
invalid_ch >> Edge(style="dashed", color="red") >> pager
invalid_dash >> operator
operator >> Edge(style="dashed", label="corrected\nmessage") >> results_ch
# Monitoreo
invalid_ch >> Edge(style="dotted") >> monitoring
from diagrams import Diagram, Cluster, Edge
from diagrams.onprem.client import User
from diagrams.onprem.compute import Server
from diagrams.saas.alerting import Pagerduty
from diagrams.azure.compute import FunctionApps, ContainerApps
from diagrams.azure.database import CosmosDb
from diagrams.azure.devops import ApplicationInsights
from diagrams.azure.integration import ServiceBus
with Diagram("Invalid Message Channel - Healthcare HL7 (Azure)", show=False, direction="LR"):
with Cluster("Sistemas Clínicos Fuente"):
lis = Server("LIS\n(Laboratorio)")
ris = Server("RIS\n(Radiología)")
pharmacy = Server("Pharmacy\nSystem")
adt = Server("ADT\nSystem")
with Cluster("Integration Layer"):
engine = ContainerApps("Integration\nEngine\n(Container App)")
with Cluster("Service Bus - Integration Channels"):
results_ch = ServiceBus("clinical.hl7.results\n(Queue - valid)")
pharmacy_ch = ServiceBus("clinical.hl7.pharmacy\n(Queue - valid)")
adt_ch = ServiceBus("clinical.hl7.adt\n(Queue - valid)")
invalid_ch = ServiceBus("clinical.hl7.invalid\n(Queue - INVALID\nMESSAGE CHANNEL)")
with Cluster("Consumidores (Azure Functions)"):
emr = FunctionApps("EMR\nConsumer")
invalid_dash = FunctionApps("Invalid Message\nDashboard")
with Cluster("Almacenamiento"):
emr_db = CosmosDb("Cosmos DB\n(EMR Store)")
invalid_db = CosmosDb("Cosmos DB\n(Invalid Messages)")
pager = Pagerduty("PagerDuty\nAlerts")
operator = User("Integration\nAnalyst")
monitoring = ApplicationInsights("Application Insights\n(Invalid Rate)")
# Fuentes al Integration Engine
lis >> engine
ris >> engine
pharmacy >> engine
adt >> engine
# Flujo válido
engine >> Edge(color="green", label="valid") >> results_ch
engine >> Edge(color="green", label="valid") >> pharmacy_ch
engine >> Edge(color="green", label="valid") >> adt_ch
# Flujo inválido (custom dead-letter with reason)
engine >> Edge(color="red", style="bold", label="invalid\n(custom reason)") >> invalid_ch
# Consumo válido
results_ch >> emr >> emr_db
pharmacy_ch >> emr
adt_ch >> emr
# Consumo de inválidos
invalid_ch >> invalid_dash >> invalid_db
invalid_ch >> Edge(style="dashed", color="red") >> pager
invalid_dash >> operator
operator >> Edge(style="dashed", label="corrected\nmessage") >> results_ch
# Monitoreo
invalid_ch >> Edge(style="dotted") >> monitoring
Explicación del Diagrama¶
El diagrama muestra la arquitectura de Invalid Message Channel para la integración HL7 en un hospital:
- Sistemas clínicos fuente (LIS, RIS, Pharmacy, ADT) envían mensajes HL7 al Integration Engine.
- El Integration Engine valida cada mensaje. Los mensajes válidos se envían a los canales correspondientes (verde). Los mensajes inválidos se envían al Invalid Message Channel (rojo).
- El EMR Consumer consume de los canales válidos y actualiza la historia clínica.
- El Invalid Message Dashboard consume del canal de inválidos, almacena los detalles en una base de datos y presenta la información al analista de integración.
- PagerDuty envía alertas inmediatas para mensajes inválidos de alta severidad.
- El analista de integración diagnostica, corrige y reenvía mensajes al canal principal.
- Grafana monitorea la tasa de mensajes inválidos por sistema fuente.
Correspondencia Patrón ↔ Diagrama¶
| Concepto del Patrón | Componente del Diagrama |
|---|---|
| Productor (fuente del mensaje) | LIS, RIS, Pharmacy, ADT |
| Canal Principal | clinical.hl7.results, clinical.hl7.pharmacy, clinical.hl7.adt |
| Validación | Integration Engine (validación estructural) |
| Invalid Message Channel | clinical.hl7.invalid |
| Mensaje enriquecido con error metadata | Payload original + error details + severity |
| Proceso de corrección | Invalid Message Dashboard + Integration Analyst |
| Feedback al productor | Reporte semanal de tasa de invalidez por sistema fuente |
| Reprocesamiento | Analista reenvía mensaje corregido al canal principal |
11. Beneficios¶
Impacto Técnico¶
- Resiliencia del consumidor: mensajes inválidos no bloquean el procesamiento de mensajes válidos. El consumidor sigue operando sin interrupción.
- Zero data loss: ningún mensaje se descarta silenciosamente. Todo mensaje, válido o inválido, tiene un destino definido y monitoreable.
- Diagnóstico completo: el mensaje inválido se preserva con toda su metadata original más la información de error, proporcionando contexto completo para diagnóstico.
- Desacoplamiento de error handling: la lógica de procesamiento de mensajes válidos y la lógica de manejo de mensajes inválidos están separadas en diferentes consumidores, cada uno optimizado para su función.
Impacto Organizacional¶
- SLA de resolución definible: con un canal de inválidos monitoreable, la organización puede definir SLAs de resolución por severidad (CRITICAL: 30 min, HIGH: 4 horas, MEDIUM: 24 horas).
- Métricas de calidad por productor: la tasa de mensajes inválidos por sistema fuente es un KPI de calidad de integración que incentiva a los equipos productores a mejorar su validación.
- Auditoría completa: en dominios regulados, el canal de inválidos proporciona evidencia de que todos los mensajes se gestionan (procesados o manejados como inválidos), cumpliendo requisitos de compliance.
Impacto Operacional¶
- Alertas proactivas: la aparición de mensajes inválidos dispara alertas antes de que el impacto de negocio se materialice. Un pico de mensajes inválidos del LIS indica un problema que se puede resolver antes de que los médicos se queden sin resultados.
- Tendencias de calidad: monitorear la tasa de invalidez a lo largo del tiempo revela mejoras o degradaciones en la calidad de las integraciones.
- Capacidad de reprocesamiento: los mensajes corregidos pueden reenviarse al canal principal para procesamiento normal, completando el ciclo de recuperación.
Beneficios de Mantenibilidad y Evolución¶
- Detección temprana de incompatibilidades: cuando un sistema fuente cambia su formato de mensaje (nueva versión de HL7, nuevo campo, campo renombrado), los mensajes inválidos aparecen inmediatamente en el canal, alertando del cambio antes de que cause impacto masivo.
- Testing en producción controlado: la tasa de mensajes inválidos después de un despliegue indica si el nuevo código introdujo regresiones en la validación.
- Documentación implícita: los tipos de errores que aparecen en el canal de inválidos documentan implícitamente las expectativas de formato de cada consumidor.
12. Desventajas y Riesgos¶
Complejidad Añadida¶
- Lógica de validación: el consumidor necesita lógica de validación explícita que puede ser compleja, especialmente para formatos como HL7 con muchas reglas de estructura.
- Enriquecimiento de errores: construir el mensaje de error con toda la metadata de diagnóstico añade código y complejidad al consumidor.
- Proceso operacional: el canal de inválidos requiere un proceso de revisión y corrección. Sin este proceso, el canal acumula mensajes sin acción.
Riesgos de Mal Uso¶
- Canal de inválidos como vertedero: si nadie revisa los mensajes inválidos, el canal se convierte en un vertedero de datos ignorados. Esto es peor que descartar: da la falsa sensación de que el problema está "manejado" cuando en realidad solo está "almacenado".
- Definición ambigua de "inválido": sin criterios claros de qué constituye un mensaje inválido, los consumidores pueden enviar al canal de inválidos mensajes que son difíciles de procesar pero no técnicamente inválidos (lazy error handling).
- Sobrecarga de alertas: si la tasa de mensajes inválidos es alta y cada mensaje genera una alerta, el equipo de operaciones sufre alert fatigue y deja de prestar atención.
Sobreingeniería¶
- Validación excesiva: validar cada campo contra cada regla posible puede rechazar mensajes que son "suficientemente buenos" para el procesamiento. Es necesario calibrar el nivel de validación.
- Dashboard sofisticado innecesario: para volúmenes bajos de mensajes inválidos, un simple log o alert es suficiente. Un dashboard completo con workflow de corrección solo se justifica a escala.
Costos de Operación¶
- Storage de mensajes inválidos: si el volumen de inválidos es alto (productores de baja calidad), el storage puede ser significativo.
- Tiempo de operador: revisar y corregir mensajes inválidos consume tiempo del equipo de integración.
- Infraestructura adicional: el canal de inválidos, el dashboard, las alertas y la base de datos de inválidos son componentes adicionales que mantener.
Anti-Patterns Relacionados¶
- Swallowing Channel: un canal donde se envían mensajes inválidos pero que nadie monitorea ni revisa. Equivale a un
catch (Exception e) { /* ignore */ }. - Invalid As Normal: un consumidor que envía tantos mensajes al canal de inválidos que el flujo "excepcional" se convierte en el flujo normal. Esto indica un problema fundamental en el productor o en la definición de validez.
13. Relación con Otros Patrones¶
Patrones Complementarios¶
- Dead Letter Channel (Capítulo 3): patrón complementario que maneja mensajes que el sistema no puede entregar (vs. Invalid Message Channel que maneja mensajes que el consumidor rechaza). Es común tener ambos canales en una arquitectura.
- Message Channel (Capítulo 2): Invalid Message Channel es un Message Channel con un propósito específico (recibir mensajes rechazados).
- Datatype Channel (Capítulo 3): un Datatype Channel con Schema Registry puede rechazar mensajes inválidos antes de que lleguen al consumidor. Los mensajes rechazados por el Schema Registry se envían al Invalid Message Channel.
- Content-Based Router (Capítulo 5): la lógica de validación en el consumidor actúa como un Content-Based Router implícito: mensajes válidos van al flujo principal, mensajes inválidos van al canal de inválidos.
Distinción Crítica: Invalid Message Channel vs. Dead Letter Channel¶
| Aspecto | Invalid Message Channel | Dead Letter Channel |
|---|---|---|
| Causa | Contenido del mensaje es inválido | Sistema no puede entregar/procesar el mensaje |
| Quién decide | El consumidor rechaza activamente | El broker/sistema después de agotar reintentos |
| Tipo de error | Formato, estructura, semántica | Timeout, consumer down, poison pill |
| Acción correctiva | Corregir el mensaje o el productor | Corregir el consumidor o la infraestructura |
| Reintentos | No tiene sentido (error determinista) | Los reintentos ya se agotaron |
| Ejemplo | HL7 con campo obligatorio vacío | Mensaje que causa OutOfMemoryError en consumer |
Patrones que Suelen Aparecer Antes o Después¶
- Antes: Datatype Channel (define qué tipo se espera) y Schema Registry (valida estructura) pueden prevenir muchos mensajes inválidos antes de que lleguen al consumidor.
- Después: Wire Tap puede copiar mensajes inválidos a un canal de monitoreo adicional para analytics.
Combinaciones Comunes¶
- Invalid Message Channel + Dead Letter Channel: ambos canales coexisten. El consumidor envía mensajes con formato inválido al Invalid Message Channel. El broker envía mensajes que causan excepciones de procesamiento (después de N reintentos) al Dead Letter Channel.
- Invalid Message Channel + Wire Tap: un Wire Tap en el canal de inválidos copia mensajes a un sistema de analytics para generar reportes de calidad de datos.
- Invalid Message Channel + Channel Adapter: cuando el productor es un sistema legacy que no puede corregirse fácilmente, un Channel Adapter puede intentar transformar/limpiar los mensajes antes de que lleguen al consumidor, reduciendo la tasa de mensajes inválidos.
Encaje en un Flujo Mayor de Integración¶
Invalid Message Channel es un componente esencial del error handling de toda arquitectura de mensajería. Junto con Dead Letter Channel, forma la estrategia completa de manejo de mensajes problemáticos. Todo canal principal debería tener un Invalid Message Channel asociado (o compartir uno común con naming convencionalizado).
14. Relevancia Actual del Patrón¶
Evaluación: Relevancia Alta¶
Argumentación¶
Invalid Message Channel es un patrón de error handling esencial que toda arquitectura de producción necesita. En la práctica moderna:
- En Apache Kafka, no hay soporte nativo de invalid message routing — el consumidor debe implementar la lógica de validación y producir en un topic de error. Frameworks como Spring Kafka proporcionan
ErrorHandlingDeserializerque automatiza el routing de mensajes que fallan deserialización. - En Azure Service Bus, existe dead-lettering automático por razones configurables, pero la distinción entre "inválido" (contenido malo) y "no entregable" (processing failure) debe implementarla el consumidor.
- En RabbitMQ, los mensajes rechazados con
basic.nackpueden enrutarse a un exchange de dead-letter. El consumidor puede usarbasic.rejectconrequeue=falsepara enviar mensajes inválidos a un DLX configurado como invalid message exchange. - En AWS SQS, los mensajes que exceden el
maxReceiveCountvan a una Dead Letter Queue. Para mensajes inválidos específicamente, el consumidor debe implementar el routing a una SQS queue de inválidos.
Cómo Se Implementa Hoy¶
| Plataforma | Implementación | Soporte Nativo |
|---|---|---|
| Kafka | Consumer produce en .invalid topic + ErrorHandlingDeserializer | Parcial (framework-level) |
| RabbitMQ | basic.reject → DLX configurado como invalid exchange | Parcial (DLX reutilizado) |
| Azure Service Bus | Dead-letter con razón personalizada + consumer-side routing | Parcial (dead-letter nativo) |
| AWS SQS | Consumer envía a SQS queue de inválidos explícitamente | No nativo |
| Google Pub/Sub | Consumer publica en topic de inválidos explícitamente | No nativo |
| Spring Integration | errorChannel + routing por tipo de excepción | Sí (framework-level) |
| Apache Camel | onException().to("kafka:topic.invalid") | Sí (framework-level) |
Qué Parte Sigue Siendo Esencial¶
- Separar mensajes que el consumidor no puede entender de mensajes que el sistema no puede entregar: la distinción conceptual entre Invalid Message Channel y Dead Letter Channel sigue siendo fundamental para un error handling correcto.
- Preservar mensajes inválidos para diagnóstico: en ningún escenario moderno es aceptable descartar silenciosamente un mensaje de negocio.
- Monitorear la tasa de invalidez como indicador de calidad: la observabilidad de los mensajes inválidos es un pilar del error handling en producción.
15. Implementación en Arquitecturas Modernas¶
Apache Kafka con Spring Kafka¶
// Configuración de ErrorHandlingDeserializer
// Mensajes que fallan deserialización van automáticamente al error handler
@Bean
public ConsumerFactory<String, LabResult> consumerFactory() {
Map<String, Object> props = new HashMap<>();
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
ErrorHandlingDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
ErrorHandlingDeserializer.class);
props.put(ErrorHandlingDeserializer.VALUE_DESERIALIZER_CLASS,
AvroDeserializer.class);
return new DefaultKafkaConsumerFactory<>(props);
}
// Error handler que envía mensajes inválidos al Invalid Message Channel
@Bean
public CommonErrorHandler errorHandler(KafkaTemplate<String, byte[]> template) {
DeadLetterPublishingRecoverer recoverer =
new DeadLetterPublishingRecoverer(template,
(record, ex) -> new TopicPartition(
record.topic() + ".invalid", record.partition()));
return new DefaultErrorHandler(recoverer, new FixedBackOff(0L, 0));
// FixedBackOff(0, 0) = no retries for deserialization errors
}
Apache Camel¶
// Route con Invalid Message Channel
from("kafka:clinical.hl7.results")
.onException(HL7ValidationException.class)
.handled(true)
.setHeader("X-Error-Reason", simple("${exception.message}"))
.setHeader("X-Rejected-At", simple("${date:now:yyyy-MM-dd'T'HH:mm:ss'Z'}"))
.setHeader("X-Original-Topic", constant("clinical.hl7.results"))
.to("kafka:clinical.hl7.invalid")
.end()
.process(exchange -> validateHL7(exchange))
.to("bean:emrConsumer");
RabbitMQ con Dead Letter Exchange como Invalid Channel¶
// Queue con DLX configurado para mensajes inválidos
{
"queue": "clinical.hl7.results",
"arguments": {
"x-dead-letter-exchange": "clinical.invalid",
"x-dead-letter-routing-key": "hl7.invalid"
}
}
// Consumer usa basic.reject(requeue=false) para mensajes inválidos
// El mensaje se redirige automáticamente al exchange "clinical.invalid"
Azure Service Bus con Dead-Letter personalizado¶
// Consumer en Azure Service Bus que envía mensajes inválidos a dead-letter
// con razón personalizada
await receiver.DeadLetterMessageAsync(message,
deadLetterReason: "InvalidHL7Format",
deadLetterErrorDescription: "OBX-3 field empty in segment 3");
// Receptor del dead-letter sub-queue
var dlqReceiver = client.CreateReceiver(
"clinical-hl7-results",
"emr-subscription",
new ServiceBusReceiverOptions {
SubQueue = SubQueue.DeadLetter
});
AWS SQS con Invalid Message Queue¶
# Consumer que redirige mensajes inválidos a SQS queue separada
import boto3
import json
sqs = boto3.client('sqs')
MAIN_QUEUE = 'https://sqs.eu-west-1.amazonaws.com/123456/clinical-hl7-results'
INVALID_QUEUE = 'https://sqs.eu-west-1.amazonaws.com/123456/clinical-hl7-invalid'
def process_message(message):
try:
body = json.loads(message['Body'])
validate_hl7(body) # raises InvalidHL7Error if invalid
process_valid_hl7(body)
except InvalidHL7Error as e:
# Send to Invalid Message Channel with error metadata
sqs.send_message(
QueueUrl=INVALID_QUEUE,
MessageBody=message['Body'],
MessageAttributes={
'ErrorReason': {'DataType': 'String', 'StringValue': str(e)},
'OriginalQueue': {'DataType': 'String', 'StringValue': 'clinical-hl7-results'},
'RejectedAt': {'DataType': 'String', 'StringValue': datetime.utcnow().isoformat()}
}
)
finally:
# Always delete from main queue (handled either way)
sqs.delete_message(QueueUrl=MAIN_QUEUE, ReceiptHandle=message['ReceiptHandle'])
16. Consideraciones de Gobierno y Operación¶
Observabilidad¶
- Tasa de invalidez por canal: porcentaje de mensajes que van al Invalid Message Channel vs. mensajes procesados correctamente. Una tasa > 1% indica problema en el productor.
- Tasa de invalidez por sistema fuente: si un sistema fuente genera el 80% de los mensajes inválidos, ese sistema necesita atención prioritaria.
- Distribución de tipos de error: ¿la mayoría de errores son de formato, de campos faltantes, de valores fuera de rango? La distribución orienta las acciones correctivas.
- Tiempo medio de resolución: ¿cuánto tarda un mensaje inválido en ser diagnosticado y resuelto? Este KPI mide la efectividad del proceso operacional.
Monitoreo¶
- Alerta por umbral de volumen: si más de N mensajes inválidos aparecen en una ventana de M minutos, alerta inmediata (puede indicar fallo masivo en un productor).
- Alerta por severidad: mensajes inválidos con severidad CRITICAL generan alerta inmediata independientemente del volumen.
- Alerta por antigüedad: mensajes inválidos sin resolver después de X horas generan escalación.
- Dashboard operacional: vista consolidada de mensajes inválidos pendientes por sistema fuente, tipo de error, severidad y antigüedad.
Versionado¶
- Esquema del mensaje de error: el formato del mensaje en el canal de inválidos (payload original + metadata de error) debe estar versionado y documentado.
- Evolución de reglas de validación: cuando se añaden nuevas reglas de validación, mensajes que antes eran válidos pueden volverse inválidos. El despliegue de nuevas reglas debe monitorearse con atención al impacto en la tasa de invalidez.
Seguridad¶
- Datos sensibles en mensajes inválidos: los mensajes inválidos pueden contener datos de pacientes (PHI), datos financieros (PCI) u otra información sensible. El canal de inválidos debe tener las mismas restricciones de acceso y cifrado que el canal principal.
- Acceso al dashboard: solo personal autorizado (equipo de integración, no helpdesk general) debe acceder al dashboard de mensajes inválidos para ver payloads completos.
Retención¶
- Retención regulada: en dominios regulados (salud, finanzas), los mensajes inválidos deben retenerse por el período requerido por la regulación (HIPAA: 6 años, PCI-DSS: 1 año).
- Retención operacional: fuera de requisitos regulatorios, los mensajes inválidos resueltos pueden purgarse después de un período razonable (30-90 días).
- Archivado: mensajes inválidos resueltos pero con requisito de retención pueden archivarse a storage de bajo costo (S3 Glacier, Azure Archive).
Proceso de Corrección¶
- Workflow definido: cada mensaje inválido debe pasar por un workflow: Nuevo → En Revisión → Diagnosticado → Corregido → Reenviado → Resuelto.
- Corrección manual: un operador edita el mensaje, lo corrige y lo reenvía al canal principal.
- Corrección semi-automática: reglas de corrección automática para errores comunes (formato de fecha, encoding) con revisión humana antes de reenvío.
- Escalación: mensajes que no se resuelven en el SLA definido escalan automáticamente al siguiente nivel.
Performance¶
- Impacto en el consumidor: la validación y el envío al canal de inválidos añaden latencia al procesamiento de cada mensaje. La validación debe ser eficiente (no hacer llamadas a bases de datos para cada campo).
- Batch de inválidos: si el volumen de inválidos es alto, el consumidor puede acumular mensajes inválidos en un buffer y enviarlos en batch al canal de inválidos.
17. Errores Comunes¶
No Distinguir Invalid Message Channel de Dead Letter Channel¶
El error más frecuente: usar un solo canal para mensajes "que no se pudieron procesar" sin distinguir entre contenido inválido y entrega fallida. Resultado: mensajes que necesitan corrección de contenido se mezclan con mensajes que necesitan corrección de infraestructura. Los procesos de resolución son diferentes y mezclarlos produce confusión y SLAs incumplidos.
Canal de Inválidos Sin Proceso de Revisión¶
Crear el canal de inválidos pero no establecer un proceso de revisión es equivalente a escribir logs que nadie lee. Los mensajes se acumulan indefinidamente, y el canal de inválidos da la falsa tranquilidad de que "los errores están manejados". Solución: definir ownership del canal de inválidos, SLAs de resolución y alertas de mensajes sin resolver.
Enviar Mensajes al Canal de Inválidos Sin Metadata de Error¶
Un mensaje inválido sin información de por qué fue rechazado es imposible de diagnosticar eficientemente. El operador debe reproducir el error, lo cual consume tiempo. Solución: siempre incluir la razón del rechazo, el campo/segmento problemático, el consumidor que rechazó y el timestamp.
Definición Ambigua de "Inválido"¶
Sin criterios claros, los consumidores envían al canal de inválidos cualquier mensaje que resulte difícil de procesar, incluyendo mensajes válidos con datos inesperados. Esto infla artificialmente la tasa de invalidez y reduce la señal útil. Solución: definir explícitamente qué errores son "inválidos" (formato, estructura, tipo desconocido) vs. qué errores son "de procesamiento" (lógica de negocio, dependencias no disponibles).
No Monitorear la Tasa de Invalidez¶
Sin monitoreo de la tasa de invalidez, un productor puede generar miles de mensajes inválidos durante horas o días sin que nadie lo detecte. Solución: alerta cuando la tasa de invalidez supera un umbral por ventana de tiempo (por ejemplo, > 0.5% en una hora).
Validación Solo en el Consumidor, No en el Productor¶
Si toda la validación ocurre en el consumidor, los mensajes inválidos consumen bandwidth y recursos del canal principal antes de ser rechazados. Solución: implementar validación también en el productor (Schema Registry, validación pre-envío) para prevenir la mayoría de mensajes inválidos en origen.
18. Conclusión Técnica¶
Invalid Message Channel es el patrón de error handling que proporciona resiliencia y trazabilidad ante mensajes que un consumidor no puede comprender. Su principio es claro: nunca descartar silenciosamente un mensaje, nunca bloquear el procesamiento por un mensaje inválido, y siempre preservar el mensaje problemático con contexto de diagnóstico suficiente para resolución.
Cuándo aporta valor: en toda arquitectura de mensajería donde los productores no están completamente controlados o donde la pérdida de datos es inaceptable. En la práctica, esto incluye la mayoría de los sistemas de producción, especialmente aquellos con integraciones con sistemas legacy, terceros o multi-equipo.
Cuándo evita problemas importantes: cuando un sistema fuente introduce un cambio no coordinado en el formato de sus mensajes, Invalid Message Channel es la red de seguridad que preserva los mensajes afectados, alerta al equipo de operaciones y permite la recuperación. Sin este patrón, el cambio produce pérdida de datos o bloqueo del procesamiento.
Cuándo no conviene adoptarlo: en prototipos tempranos con un solo productor completamente controlado y volúmenes bajos, la complejidad del patrón puede ser desproporcionada. Un simple logging de errores puede ser suficiente. Sin embargo, la transición de "loguear y seguir" a Invalid Message Channel debería hacerse antes de llegar a producción.
Recomendación para arquitectos: implemente Invalid Message Channel como parte estándar de toda arquitectura de mensajería. Defina claramente qué constituye un mensaje "inválido" vs. un mensaje "no procesable" (para Dead Letter Channel). Incluya siempre metadata de diagnóstico en el mensaje de error. Establezca un proceso operacional de revisión con SLAs por severidad. Monitoree la tasa de invalidez como indicador de calidad de las integraciones. Y sobre todo, distinga explícitamente entre Invalid Message Channel (el consumidor rechaza por contenido) y Dead Letter Channel (el sistema no puede entregar por infraestructura/procesamiento). Ambos patrones coexisten y se complementan, pero confundirlos produce un manejo de errores ineficaz.


