Retry Topologies
Pregunta y alcance
Cuando un consumidor no puede procesar un mensaje ahora, ¿dónde queda, cuándo vuelve a intentarse y quién controla ese ciclo? Esta perspectiva aplica retry a Messaging: conserva sus condiciones y presupuestos, y explica cómo se materializan en almacenamiento, redelivery, routing y operación.
Broker -> Consumer -> processing failure
-> clasificar / conservar / reprogramar / resolverLa topología determina dónde espera la intención, quién conserva la responsabilidad, qué trabajo puede seguir y cuándo termina el retry automático. No existe una única distribución correcta de colas, consumidores y temporizadores.
Immediate Retry
El mismo consumidor vuelve a intentar sin espera significativa: receive -> fail -> retry immediately. Puede servir para una contención o race condition extremadamente breve, si hay evidencia de que repetir es seguro y útil.
Una dependencia indisponible probablemente producirá el mismo fallo. Repetir intensivamente consume CPU y conexiones; devolver inmediatamente al broker agrega tráfico de entregas. RabbitMQ advierte que requeue puede formar loops costosos de redelivery. No es idéntico al retry local, pero comparte el riesgo de insistir sin progreso. Acknowledgements y requeue.
Delayed Retry
failure -> delay -> redelivery separa intentos para dar margen a la recuperación. La demora puede ser fija, creciente o dependiente de señales del servicio. backoff define el espaciamiento y jitter reduce sincronización; aquí no se redefinen sus fórmulas.
El tiempo programado indica cuándo el mensaje puede volver a estar disponible, no garantiza ejecución puntual: backlog, consumidores y capacidad influyen. Azure Service Bus permite publicar mensajes programados para activación posterior, un ejemplo de scheduling sin exigir una cola física por demora. Scheduled messages.
Residencia, Retry Queue y transferencia
Una retry queue dedicada retira el caso del camino principal y lo conserva hasta devolverlo al consumidor:
main -> consumer -> failure -> retry queue
-> delay -> main / consumerTambién existen delayed delivery, scheduled redelivery y republicación mediante un scheduler durable. La política temporal no exige colas separadas. Un temporizador exclusivamente en memoria necesita recuperación si cae el proceso. El consumidor o middleware clasifica el fallo y selecciona la siguiente etapa; broker o scheduler materializa la espera. Definir quién persiste ese estado y quién recupera una programación fallida evita una responsabilidad sin dueño.
En SQS, el mensaje recibido permanece en la cola, temporalmente invisible; si no se elimina y vence la visibilidad, puede entregarse otra vez. Visibility timeout gobierna ese periodo de procesamiento, no equivale automáticamente a toda la política de retry. SQS visibility timeout.
Republicar y reconocer el original introduce una frontera: ack primero puede perder la intención; publicar primero y caer puede duplicarla. Se necesita conocer confirmación, routing y atomicidad reales, o una transferencia durable diseñada explícitamente. Confirmar el traslado no confirma el efecto de negocio.
Tiered Retry
Una política puede distinguir ventanas cortas, medias y largas: main -> retry-10s -> retry-1m -> retry-10m. Los intervalos son ilustrativos; scheduling puede representar la misma política sin tres colas literales.
Cada nivel añade routing, consumidores, configuración y métricas; más infraestructura no garantiza recuperación. Retención y expiración deben cubrir las esperas previstas. Conservar edad original y contador acumulado evita que cada traslado reinicie límites. Hay que comprobar también el ordering entre etapas.
Blocking y Non-Blocking
| Aspecto | Blocking retry | Non-blocking retry |
|---|---|---|
| Residencia | Mensaje asociado al worker, partición o flujo. | Mensaje transferido o programado fuera del camino principal. |
| Capacidad | Puede retener slots, locks o progreso de la partición. | Libera capacidad principal, pero usa almacenamiento y consumidores adicionales. |
| Ordering | Puede conservar una secuencia si bloquea su progreso. | Puede dejar pasar mensajes posteriores. |
| Costo | Head-of-line blocking y trabajo sano demorado. | Routing, transferencia y coordinación adicionales. |
Blocking no implica necesariamente un thread dormido; la espera asíncrona también puede retener un slot. MassTransit documenta retries en memoria que mantienen ocupado el mensaje y pueden agotar concurrencia durante esperas largas. Message Retry.
Ninguna opción gana siempre: importa qué secuencia debe esperar y qué capacidad puede ocuparse.
Ordering y concurrencia
Si llegan A, B, C, A falla y se aparta, los efectos pueden aparecer como B, C, A. Puede ser válido para actualizaciones independientes e incorrecto si B depende de A.
Definir entity/workflow identity y partition keys permite evaluar ordering por clave, sin bloquear necesariamente todas las entidades. Conservar la clave al republicar no conserva por sí solo el orden: A puede estar en otra etapa mientras B avanza. Hacen falta decisiones sobre pausa por clave, versiones, secuencias o tratamiento de eventos tardíos.
Spring Kafka advierte que trasladar mensajes a retry topics pierde las garantías de orden del topic original. Es un ejemplo concreto del trade-off, no una regla de implementación universal. Non-blocking retry topology.
Identidad y protección del efecto
Un nuevo envelope o ID de transporte no implica una nueva operación de negocio. Conservar identidad lógica, parámetros, origen y correlación permite reconocer la intención; cada tentativa puede tener su propio ID de tracing.
at-least-once admite presentaciones repetidas, sin exigir efectos repetidos. idempotency describe el efecto de repetir; deduplication reconoce repeticiones bajo una identidad y retención. idempotent-consumer aplica esa propiedad al consumidor y inbox-pattern puede coordinar reconocimiento y efecto local. Ninguno promete exactamente una ejecución ni protege automáticamente APIs externas.
Fallos elegibles y Poison Messages
Un Timeout, fallo temporal de red, lock transitorio, sobrecarga o rate limit con condición de reintento pueden ser elegibles. Aun así, hay que comprobar incertidumbre del efecto y presupuesto: la sobrecarga no mejora por recibir más trabajo.
Payload inválido, schema incompatible, rechazo definitivo del negocio, credenciales/configuración incorrectas o ausencia definitiva de un recurso normalmente necesitan un cambio externo. La clasificación depende del contrato; repetir el mismo fallo determinista no corrige su causa.
Un poison message falla repetiblemente por su contenido o incompatibilidad con el procesamiento. Un fallo transitorio aislado no basta para clasificarlo así. Apartarlo para inspección puede ser preferible a bloquear indefinidamente una secuencia.
Retry Budget y overload
Limitar intentos totales, tiempo acumulado, edad máxima, deadline de negocio y capacidad agregada para retries. Una operación durable puede sobrevivir a la solicitud HTTP original; eso no elimina la fecha hasta la que su efecto sigue siendo válido.
10,000 mensajes fallidos x 5 retries = 50,000 intentos adicionalesEl cálculo ilustra amplificación, no costo completo: faltan duración, tamaño y retries internos. Una caída acumula mensajes y una oleada posterior puede sostener overload e impedir recuperar la dependencia. retry-storms distingue cuándo esas reentregas mantienen el feedback de degradación, en lugar de aportar progreso. bulkhead puede aislar capacidad; backpressure puede reducir adquisiciones upstream y admission-control revisar nuevos compromisos. load-shedding exige distinguir demanda no aceptada de obligaciones durables; queue-management permite revisar espera y edad a través de las colas de reintento. Ningún control vuelve ilimitada la recuperación.
Agotamiento, DLQ y recuperación
Agotar la política termina el retry automático, no completa la intención. Una dead-letter-queue puede recibir casos agotados o no elegibles; no es obligatoria. Otra opción es una obligación pendiente con responsable y recuperación explícitos, sin pérdida silenciosa.
Retry queue conserva la intención de continuar automáticamente; DLQ transfiere responsabilidad a inspección u otro proceso. Enterprise Integration Patterns describe Dead Letter Channel para mensajes que no pueden o no deben entregarse. Dead Letter Channel.
Redrive reintroduce casos apartados; replay reprocesa historial deliberadamente. Ambos requieren revisar estado actual, ordering y vigencia de Idempotency/Deduplication. Si cambió la intención, no debe disfrazarse de retry idéntico.
Ejemplo y operación
Order Events entrega ReserveInventory, intención reserve-order-42, a Inventory Consumer. La DB falla en los intentos 1 y 2; una política ilustrativa programa esperas de 10 s y 1 min, con variación temporal. El intento 3 confirma la reserva o transfiere el caso a recuperación operacional.
Todas las tentativas conservan la identidad. Si la reserva ya se confirmó y se perdió el ack, se reconoce el efecto sin descontar stock otra vez. Otros eventos pueden adelantarse durante las esperas; cancelar el pedido cambia qué recuperación es válida. Los intentos adicionales consumen capacidad aunque no produzcan otra reserva.
Observar backlog y edad por etapa, intentos acumulados, próximo vencimiento, errores, transferencias fallidas y efecto confirmado. Registrar política, responsables y motivos sin volcar datos sensibles. reliable-messaging conecta publicación, procesamiento, reintento y reparación.