Módulo 7: Reference Architectures And Domain Practice

2. Patrón: procesamiento asíncrono por colas

Descripción

Este patrón es distinto a los otros cuatro de este módulo por una razón concreta: no es una arquitectura hipotética que dibujas para el examen — es, con precisión, la arquitectura que Andes Cargo ya opera, verificada de verdad en aws-serverless-and-containers-guide Módulo 4. El Módulo 3, lección 2, de esta guía ya te dio el vocabulario completo de SQS, SNS y EventBridge. Esta lección hace algo distinto: te enseña a leer tu propia infraestructura ejecutada como si fuera, por primera vez, un patrón de arquitectura de referencia con nombre propio — el que un diagrama de estudio genérico dibujaría como "productor → cola → consumidor → DLQ", y que tú ya construiste con tus propias manos.

Conexión con el módulo

La lección 1 te dio un patrón que ninguna guía hermana construyó de verdad (3 capas desacopladas, conceptual en las tres piezas nuevas). Esta lección es el reverso exacto: un patrón con evidencia de ejecución real, del que solo falta aprender a nombrarlo como el examen lo nombra.


El diagrama de referencia: la forma genérica del patrón

Antes de ver la versión real de Andes Cargo, vale la pena fijar la forma más simple del patrón —la que un escenario de examen describe con más frecuencia—, porque el examen rara vez pide la arquitectura completa con Step Functions y EventBridge que Andes Cargo construyó; con frecuencia pide solo su núcleo:

   PATRÓN DE REFERENCIA: PROCESAMIENTO ASÍNCRONO POR COLAS (FORMA MÍNIMA)

   Productor ──publica mensaje──▶ Amazon SQS (cola principal)
   (API, servicio,                       │
    evento de S3, etc.)                  │ Lambda lee de la cola (event source mapping)
                                          ▼
                                  Función Lambda (consumidor)
                                          │
                          ┌───────────────┴───────────────┐
                          ▼                                ▼
                  procesa con éxito                falla tras maxReceiveCount
                  (borra el mensaje                intentos de reintento
                  de la cola)                                │
                                                               ▼
                                                    Dead-Letter Queue (DLQ)
                                                    — la red de seguridad

El mecanismo, con precisión: un productor publica un mensaje en una cola de SQS, sin saber ni necesitar saber quién lo va a consumir — el mismo principio de desacoplamiento del Módulo 3, lección 2. Una función Lambda, configurada con esa cola como event source, recibe el mensaje, lo procesa, y lo borra de la cola solo si el procesamiento termina con éxito. Si Lambda falla en procesar un mensaje repetidamente —agotando el número de intentos configurado en maxReceiveCount—, SQS mueve automáticamente ese mensaje a una Dead-Letter Queue separada, en vez de perderlo o reintentarlo indefinidamente.


La versión real: lo que Andes Cargo ya construyó, leído como este patrón

El Módulo 3, lección 2, ya citó la arquitectura completa de Andes Cargo, ejecutada de verdad en aws-serverless-and-containers-guide Módulo 4:

   ANDES CARGO, LEÍDO COMO EL PATRÓN DE ESTA LECCIÓN (EJECUTADO, aws-serverless M4)

   S3 (andes-cargo-shipment-docs)
        │ notificación de EventBridge
        ▼
   EventBridge (bus default) ──regla shipment-manifest-uploaded-rule──▶ Step Functions
                                                                         (ShipmentManifestWorkflow)
                                                                              │ invoca process-shipment-manifest
                                                                              │ RetryPolicy (3 intentos)
                                                                              ▼ si falla igual, tras reintentar
                                                          SQS (andes-cargo-events-dlq) ── la red de seguridad

La diferencia entre el diagrama genérico de arriba y esta versión real no es de fondo — es de piezas intermedias. Donde el patrón mínimo tiene una sola cola SQS como punto de entrada, Andes Cargo usa EventBridge (para desacoplar el origen del evento — una subida a S3 — de quién lo procesa) y Step Functions (para orquestar el flujo de process-shipment-manifest con reintentos explícitos por paso). El elemento que no cambia, en ninguna de las dos versiones, es el final: una Dead-Letter Queue que captura lo que falló después de agotar los reintentos, para que un humano pueda inspeccionarlo después, en vez de perderlo silenciosamente.

La decisión de examen: el examen no exige que reconozcas la arquitectura exacta de Andes Cargo — exige que reconozcas el patrón: cualquier escenario donde un productor no debe bloquearse esperando a un consumidor, y donde una falla de procesamiento no debe perder el mensaje original, señala este patrón, sin importar si las piezas intermedias son SQS solo, o SQS + EventBridge + Step Functions como en Andes Cargo. La pieza que siempre debe estar presente para que el patrón esté completo es la Dead-Letter Queue — un flujo asíncrono sin DLQ configurada es un patrón incompleto, incluso si el resto de la arquitectura es correcta.


La justificación por dominio

Secure: el rol del consumidor, con mínimo privilegio

LambdaManifestProcessorRole —el rol real de process-shipment-manifest, citado en el Módulo 1, lección 4— otorga acceso únicamente a la tabla Shipments y al bucket andes-cargo-shipment-docs, nunca dynamodb:* ni s3:* sobre toda la cuenta. El mismo principio aplica al rol de ejecución de cualquier consumidor de este patrón: acceso de lectura a la cola específica, y acceso de escritura únicamente a los recursos que el procesamiento necesita tocar, nada más.

Resilient: la cola como amortiguador de picos, y la DLQ como red de seguridad

Este es el dominio donde el patrón completo brilla, y la razón por la que el Módulo 3, lección 2, ya lo presentó como la solución al acoplamiento fuerte. Una cola de SQS absorbe picos de tráfico de producción sin que el productor tenga que esperar a que el consumidor esté disponible — si el consumidor está lento o momentáneamente caído, los mensajes simplemente se acumulan en la cola, sin pérdida, hasta que el consumidor vuelve a procesar. La DLQ resuelve el caso contrario: cuando el problema no es velocidad, sino un mensaje que el consumidor nunca puede procesar con éxito (datos mal formados, por ejemplo) — sin DLQ, ese mensaje se reintentaría indefinidamente, bloqueando el procesamiento de mensajes sanos detrás de él en algunos diseños, o se perdería silenciosamente en otros.

High-Performing: Lambda escala con la profundidad de la cola, sin aprovisionar nada por adelantado

Un consumidor basado en Lambda escala su número de ejecuciones concurrentes en función de cuántos mensajes hay pendientes en la cola —dentro del límite de concurrencia configurado—, sin que nadie tenga que aprovisionar capacidad de cómputo por adelantado ni adivinar el tráfico esperado. Es el mismo principio stateless que el Módulo 3, lección 2, ya estableció sobre process-shipment-manifest: cualquier invocación puede correr en cualquier entorno de ejecución, así que escalar horizontalmente —más mensajes, más invocaciones concurrentes— no exige ninguna coordinación especial.

Cost-Optimized: pagas por mensaje procesado, no por infraestructura ociosa

Ni SQS ni Lambda cobran por capacidad reservada en este patrón — SQS cobra por solicitud, Lambda cobra por invocación y tiempo de ejecución. Comparado con un consumidor siempre encendido (una instancia EC2 corriendo un worker que sondea la cola constantemente, aunque no haya mensajes), este patrón no tiene ningún costo de infraestructura ociosa: si no hay mensajes, no hay invocaciones, no hay cargo.

La decisión de examen: cuando un escenario menciona explícitamente "minimizar costo operativo" para una carga de procesamiento asíncrono con volumen variable e impredecible, el patrón SQS + Lambda + DLQ es, con frecuencia, la respuesta más ajustada frente a alternativas con cómputo siempre encendido — precisamente porque el costo escala con el volumen real de mensajes, no con un tamaño de infraestructura reservado por adelantado.


Errores comunes

Confundir el patrón "cola + consumidor" con "invocación directa y síncrona" (de perder el punto del desacoplamiento). Qué pasa: alguien diseña un flujo donde el productor invoca directamente a la función Lambda (síncrono), y llama a eso "procesamiento asíncrono" solo porque hay una función Lambda involucrada. Cómo detectarlo: si tu diagrama no tiene ninguna cola entre el productor y el consumidor, no es este patrón — es acoplamiento directo, con la misma fragilidad que la analogía del restaurante sin comandas (Módulo 3, lección 2) describió. Cómo corregirlo: el elemento que hace asíncrono al patrón es la cola misma — el productor publica y sigue con lo suyo, sin esperar ninguna respuesta del consumidor.

Omitir la DLQ del diagrama, asumiendo que "los reintentos son suficientes" (de dejar la red de seguridad afuera). Qué pasa: alguien diseña el flujo con SQS y Lambda, pero sin ninguna Dead-Letter Queue configurada, razonando que los reintentos automáticos ya cubren cualquier falla. Cómo detectarlo: si tu arquitectura no tiene ningún destino explícito para mensajes que fallan después de agotar los reintentos. Cómo corregirlo: los reintentos resuelven fallas temporales (el consumidor estaba momentáneamente sobrecargado); no resuelven fallas permanentes (un mensaje mal formado que nunca va a procesarse con éxito, sin importar cuántas veces se reintente) — sin DLQ, ese tipo de mensaje se pierde o bloquea el flujo, exactamente el problema que Andes Cargo resolvió con andes-cargo-events-dlq.

Asumir que este patrón exige EventBridge y Step Functions siempre, porque así lo construyó Andes Cargo (de sobre-generalizar un ejemplo real a una regla). Qué pasa: alguien, al ver la arquitectura completa de Andes Cargo, concluye que el patrón "procesamiento asíncrono por colas" siempre necesita esas tres piezas juntas. Cómo detectarlo: si tu respuesta a un escenario simple de cola + consumidor agrega EventBridge y Step Functions sin que el escenario los justifique. Cómo corregirlo: la forma mínima del patrón —SQS + Lambda + DLQ— es, con frecuencia, exactamente lo que el examen pide; EventBridge se agrega solo cuando el escenario necesita enrutamiento por contenido del evento hacia múltiples destinos, y Step Functions solo cuando el escenario necesita pasos secuenciales orquestados con estado visible — ninguna de las dos piezas es obligatoria para que el patrón exista.


❓ Pregunta de práctica — Dominios 2 y 4 (patrón combinado)

Escenario: Andes Cargo evalúa agregar un segundo tipo de procesamiento: además del manifiesto de envío, cada carga pesada requiere un cálculo de tarifa aduanera que, ocasionalmente (menos del 1% de los casos), falla porque el documento adjunto tiene un formato que el validador no reconoce. El equipo quiere que esos casos fallidos queden disponibles para revisión manual, sin bloquear el procesamiento del resto de los envíos, y sin mantener ningún servidor corriendo de forma permanente solo para este cálculo, dado que el volumen diario es bajo y muy variable.

Pregunta: ¿Cuál arquitectura resuelve ambos requisitos con el menor costo operativo?

A. Una instancia EC2 dedicada, corriendo un proceso que sondea (polling) una tabla de DynamoDB cada minuto en busca de cálculos pendientes. B. Una cola de Amazon SQS que recibe cada solicitud de cálculo, una función Lambda que la consume y la procesa, y una Dead-Letter Queue configurada para los casos que fallan tras los reintentos. C. Una invocación síncrona directa desde el sistema que genera la carga hacia una función Lambda de cálculo, sin ninguna cola intermedia. D. Un clúster de Amazon ECS con un servicio corriendo permanentemente, escuchando una cola de SQS con desiredCount fijo en 3 tareas.


✅ Respuesta correcta: B

Por qué es correcta: el patrón SQS + Lambda + DLQ resuelve los dos requisitos exactos del escenario sin ningún costo de infraestructura ociosa. La cola desacopla el momento en que se genera la solicitud de cálculo del momento en que se procesa, así que un caso fallido no bloquea el resto — se reintenta y, si sigue fallando, cae en la DLQ para revisión manual, exactamente como andes-cargo-events-dlq ya opera para los manifiestos. Al ser Lambda el consumidor, no hay ningún servidor corriendo quieto cuando no hay solicitudes pendientes — el volumen bajo y variable del escenario es, con precisión, el caso de uso textual de este patrón sobre alternativas con cómputo siempre encendido.

Por qué las demás fallan:

  • A: una instancia EC2 dedicada, sondeando cada minuto, cobra por cada minuto que existe, sin importar si hay trabajo pendiente o no — exactamente el costo de infraestructura ociosa que el escenario pide evitar, además de que el equipo tendría que mantener y parchar esa instancia.
  • C: una invocación directa y síncrona significa que el sistema que genera la carga tiene que esperar la respuesta del cálculo — si el cálculo falla, ese sistema necesita manejar el error él mismo, sin ninguna red de seguridad automática que capture el caso fallido para revisión; es el acoplamiento fuerte que este patrón existe para evitar.
  • D: un clúster de ECS con desiredCount fijo en 3 tareas mantiene tres tareas corriendo de forma permanente, sin importar el volumen real de solicitudes — para un volumen diario bajo y muy variable, es notablemente más caro que un consumidor Lambda que solo se ejecuta, y solo cobra, cuando hay mensajes reales que procesar.

Resumen y siguiente paso

En esta lección leíste, por primera vez con nombre de patrón de arquitectura de referencia, la infraestructura que Andes Cargo ya opera de verdad: SQS/EventBridge/Step Functions como el productor desacoplado del consumidor, y la Dead-Letter Queue como la pieza que ningún diseño de este patrón puede omitir. Viste la forma mínima del patrón (SQS + Lambda + DLQ) y por qué el examen la prueba con más frecuencia que la versión completa de tres piezas que Andes Cargo construyó.

Antes de avanzar deberías poder dibujar la forma mínima del patrón de memoria, y explicar en una frase por qué una arquitectura asíncrona sin DLQ está incompleta.

La lección 3 cubre el tercer patrón: el sitio estático de alto rendimiento — S3 + CloudFront + Route 53, y el trade-off de invalidación de caché.

Recursos

  1. Amazon SQS — Dead-letter queues — fuente oficial del mecanismo de DLQ que este patrón exige en cualquiera de sus formas.
  2. Using Lambda with Amazon SQS — documentación oficial del mecanismo de consumo (event source mapping) que conecta SQS con una función Lambda.
  3. aws-serverless-and-containers-guide, Módulo 4 (NIEVA) — la fuente ejecutada de verdad de la arquitectura completa de Andes Cargo que esta lección lee como patrón de referencia.
  4. Módulo 3, lección 2, de esta guía — el vocabulario completo de SQS/SNS/EventBridge, y la analogía de la cocina de un restaurante que respalda este patrón.