# Deja un mensaje, no esperes

Curso exprés sobre queues y sistemas orientados a eventos. 21 conceptos — Synchronous Call, Message Queue, Asynchronous, Producer y Consumer, Broker, Competing Consumers, Command y Event, Pub/Sub, Event-driven, Load Leveling, Idempotency, Eventual Consistency, Dead-Letter Queue y más — cada uno con su nombre en inglés, una imagen, un diagrama y una ficha con un ejemplo. Al final: un mapa de relaciones y un resumen de una página. La idea central: desacoplar el trabajo en el tiempo es como los sistemas se mantienen rápidos y sobreviven a los fallos.

- **Author:** Fedor Chishchin
- **Level:** intermediate
- **Reading time:** ~35 minutos de lectura
- **Published:** 2026-06-13
- **Source:** https://fedorthinks.com/es/learn/queues-express

---

## 1. El problema de llamar directamente

Para entender por qué existen las queues, primero hay que sentir el dolor de la alternativa sencilla: un servicio que llama a otro y lo espera. Funciona hasta el momento en que de verdad importa.

### El mapa: 21 conceptos en seis grupos

> Un mapa de metro: primero ves las líneas enteras, luego recorres estación por estación.

Primero el **problema** — por qué una llamada directa te falla. Después un capítulo por grupo: la **queue** (la idea en sí), los **roles** (quién escribe, quién lee, quién guarda), **comandos y eventos** (dos tipos de mensaje), los **beneficios** (por qué pagas) y las **partes difíciles** (qué se rompe). El último capítulo trata de cuándo usar una queue y cuándo no, e incluye un mapa de relaciones y un resumen.

_Diagram: Seis grupos de conceptos — los capítulos 1–6 los siguen. El capítulo 7 trata de elegir, más el resumen._

### Cómo leer cada concepto

> Un pasaporte: los mismos campos para todos, así es fácil compararlos.

Cada concepto a partir de aquí tiene la misma forma: su **nombre en inglés** (apréndelo — es la palabra que verás en la documentación de los brokers y en las entrevistas), una imagen de la vida cotidiana, un **diagrama** y una **ficha**: _problema_, _idea_, _ejemplo_, _coste_ y cómo se _relaciona_ con otros conceptos. Al final: un mapa de relaciones y un resumen.

### Synchronous Call — una llamada directa ata dos servicios entre sí

> Telefonear a alguien y quedarte en la línea hasta que termine la tarea — no puedes colgar, no puedes hacer nada más, y si no contesta, te quedas atascado.

La forma obvia de que el servicio A consiga que el servicio B haga algo es una **synchronous call**: A pregunta y luego espera, conteniéndolo todo hasta que B responde. Esto los **acopla** estrechamente — la velocidad de A queda ahora secuestrada por la velocidad de B, y A no puede continuar hasta que B termine. Para una respuesta rápida eso está bien. Para un trabajo lento o pesado, A pasa el tiempo congelado, esperando a otro.

_Diagram: A llamó a B y se quedó quieto: todo el trabajo lento de B es tiempo que A pasa bloqueado._

#### Synchronous Call (request–response (petición–respuesta))

- **Problema:** El que llama queda congelado hasta que el llamado responde.
- **Idea:** Preguntar, esperar la respuesta y seguir. La forma más simple de hablar.
- **Ejemplo:** El servicio de pedidos llama por HTTP al servicio de precios y espera el precio antes de mostrar el carrito.
- **Coste:** **Acoplamiento** estrecho: la velocidad y la disponibilidad de A dependen de B.
- **Relaciones:** Su dolor lo cura una **Message Queue**; para respuestas instantáneas sigue siendo la mejor opción.

### Failure Propagation — si el llamado está caído, el que llama se rompe

> Llamar al almacén para confirmar un pedido y, como nadie contesta, negarte a aceptar cualquier pedido nuevo — una puerta cerrada bloquea toda la tienda.

El problema más profundo es el fallo. Si B está caído o sobrecargado cuando A llama, la petición de A también falla — el fallo se **propaga** directamente hacia arriba en la cadena. Un solo servicio lento o roto puede paralizar todo lo que depende de él, y un pico de tráfico hacia B arrastra a A consigo. El acoplamiento estrecho significa que la debilidad se extiende, y el sistema solo está tan disponible como su parte más frágil.

_Diagram: El almacén está caído — y el error sube: fallan los pedidos, falla el pago._

#### Failure Propagation (cascading failure (fallo en cascada))

- **Problema:** El fallo de un servicio se convierte en el fallo de todos los que lo llaman.
- **Idea:** Una cadena síncrona solo es tan disponible como su eslabón más débil.
- **Ejemplo:** El almacén no responde → los pedidos dan error → el pago deja de funcionar.
- **Coste:** Un pico de tráfico hacia un servicio arrastra todo lo que tiene encima.
- **Relaciones:** Se cura con un búfer: una **Message Queue** da **Resilience** — un fallo se convierte en un retraso.

### Background Work — cierto trabajo no debería bloquear al usuario

> En una caja, pagas y te vas con tu recibo — no te quedas en la caja mientras empaquetan, envían y te mandan un correo. Las partes lentas ocurren después de que te marchas.

Mucho trabajo no necesita terminar antes de que el usuario reciba una respuesta — enviar el correo de confirmación, generar la factura, redimensionar la foto. Esto es **background work** (trabajo en segundo plano). Hacer que el usuario espere todo eso es lento e inútil. Quieres aceptar la petición, responder rápido y dejar que las partes lentas ocurran después. Una llamada directa no puede hacer eso; obliga a todos a esperar por todo.

_Diagram: La API responde de inmediato; el correo, la factura y la foto se hacen después — desde una queue._

#### Background Work (background jobs (tareas en segundo plano))

- **Problema:** El usuario espera trabajo del que su respuesta no depende.
- **Idea:** Aceptar la petición, responder rápido y hacer las partes lentas después.
- **Ejemplo:** El pago pasó — recibo ya; el correo, la factura y el redimensionado de la foto, en segundo plano.
- **Coste:** El resultado del trabajo en segundo plano no aparece al instante.
- **Relaciones:** Se hace con una **Message Queue** y **Asynchronous Processing**.

> **La pregunta de fondo:** «¿De verdad el que llama necesita esperar a que esto termine — o solo está atascado en la línea mientras corre un trabajo lento del que no depende?»

> Una llamada directa acopla dos servicios en el tiempo: el que llama espera y hereda la lentitud y los fallos del llamado. Para trabajo lento o no urgente, eso es una trampa.

## 2. La queue

La solución es dejar de llamar y empezar a enviar mensajes. Una queue es el búfer del medio que permite a un lado dejar trabajo y al otro recogerlo — desacoplándolos en el tiempo.

### Message Queue — deja el mensaje y sigue adelante

> Dejar un mensaje de voz en lugar de esperar al teléfono: dices lo que necesitas, cuelgas y sigues con tu día — lo atenderán cuando puedan.

En lugar de llamar a B y esperar, A escribe un **mensaje** que describe el trabajo y lo deja en una **queue** — una fila donde los mensajes esperan a ser procesados. A queda libre para continuar de inmediato; no le importa cuándo llegue B a ello. El mensaje es un pequeño paquete de «esto es lo que hay que hacer», entregado en lugar de ejecutado en el acto. Ese traspaso es toda la idea.

_Diagram: A deja un mensaje y sigue; los mensajes esperan en la queue; B recoge uno cuando está listo. Abajo — cómo podría verse un mensaje en sí._

#### Message Queue (queue (cola))

- **Problema:** Una llamada directa mantiene al emisor en la línea.
- **Idea:** Describir el trabajo como un **mensaje** y ponerlo en una **queue**; el receptor lo recoge por su cuenta.
- **Ejemplo:** En lugar de llamar al servicio de correo — un mensaje `SendEmail` con el número de pedido, en una queue.
- **Coste:** Una pieza móvil nueva que hay que ejecutar y entender.
- **Relaciones:** Da **Temporal Decoupling**; la guarda un **Broker**; la leen los **Consumers**.

### Temporal Decoupling — la queue es un búfer en el tiempo

> Una bandeja de entrada en un escritorio: el trabajo se acumula en ella y se atiende con calma, así que una avalancha repentina de papeles no abruma a la persona — solo hace la bandeja más alta por un rato.

La queue se sitúa entre los dos lados como un **búfer**, guardando los mensajes hasta que se procesan. Esto **los desacopla en el tiempo** (temporal decoupling): el emisor y el receptor ya no tienen que ser rápidos, estar disponibles ni siquiera estar en marcha en el mismo momento. El trabajo producido en ráfagas puede consumirse de forma constante. La queue absorbe la diferencia entre la velocidad a la que llega el trabajo y la velocidad a la que se puede hacer.

_Diagram: A la izquierda el trabajo llega a ráfagas, a la derecha se procesa de forma constante. La queue del medio absorbe la diferencia._

#### Temporal Decoupling (buffer in time (búfer en el tiempo))

- **Problema:** Ambos lados deben estar vivos y ser rápidos en el mismo momento.
- **Idea:** Un búfer entre ellos: emisor y receptor trabajan cada uno a su propio tiempo.
- **Ejemplo:** Una ráfaga de pedidos se acumula en la queue y se procesa a un ritmo constante.
- **Coste:** El trabajo puede esperar en la queue — el resultado no es instantáneo.
- **Relaciones:** La base de **Resilience** y **Load Leveling**.

### Asynchronous Processing — no esperar el resultado

> Enviar una carta en lugar de mantener una conversación — la mandas y sigues con lo tuyo, confiando en que la leerán y actuarán después, sin que tú estés allí.

Esto es trabajo **asíncrono**: el emisor no espera el resultado. Lanza el mensaje y continúa, y el resultado ocurre después, por otra vía. Renuncias a la respuesta instantánea de una llamada directa, y a cambio dejas de estar bloqueado. Para todo lo que no necesita una respuesta inmediata, ese trato es la base de los sistemas rápidos y resilientes.

_Diagram: Arriba, síncrono: A se queda esperando. Abajo, asíncrono: A envía un mensaje y sigue trabajando, y un worker hace la tarea después._

#### Asynchronous Processing (async (asíncrono))

- **Problema:** Esperar un resultado que no necesitas ahora mismo.
- **Idea:** Enviar el mensaje y seguir; el resultado ocurre después, por otra vía.
- **Ejemplo:** Un informe se genera en segundo plano; el usuario lo recibe cuando está listo.
- **Coste:** Sin respuesta instantánea; es más difícil seguir la pista de lo que pasó.
- **Relaciones:** Lo opuesto a **Synchronous Call**; trae **Eventual Consistency**.

> **La pregunta de la queue:** «¿Puedo convertir esto en un mensaje dejado en una queue — dejando que el emisor continúe de inmediato y que el trabajo ocurra cuando el otro lado esté listo?»

> Una queue es un búfer entre emisor y receptor. Deja un mensaje y sigue adelante — el trabajo queda desacoplado en el tiempo, hecho de forma asíncrona cuando el otro lado está listo.

## 3. Producers, consumers, brokers

Tres roles hacen funcionar una queue, y ponerles nombre aclara la mayor parte de la jerga. Un lado crea mensajes, otro los atiende, y algo en el medio los guarda con seguridad.

### Producer / Consumer — un lado crea trabajo, el otro lo hace

> Una cocina: los camareros cuelgan comandas y los cocineros las van descolgando una a una para prepararlas. Los dos lados nunca hablan directamente — el riel de comandas es toda la interfaz.

El lado que crea mensajes es el **producer** (o publisher); el lado que los procesa es el **consumer** (o worker). El producer deja una comanda; el consumer recoge una, hace el trabajo y pasa a la siguiente. No se conocen ni se esperan — solo conocen la queue. Esta separación limpia permite construir, escalar y cambiar cada lado por su cuenta.

_Diagram: Los producers escriben en la queue, los consumers leen de ella. Nunca se encuentran directamente._

#### Producer / Consumer (publisher / worker)

- **Qué es:** El **producer** crea mensajes; el **consumer** los toma y hace el trabajo.
- **Idea:** Los lados conocen solo la queue, no se conocen entre sí.
- **Ejemplo:** La app web deja «redimensiona esta foto»; un worker toma el mensaje y la redimensiona.
- **Trampa:** El producer no sabe cuándo, ni quién, hará el trabajo.
- **Relaciones:** Un **Broker** se sitúa entre ellos; muchos consumers en una queue son **Competing Consumers**.

### Message Broker — el broker guarda los mensajes con seguridad

> Una oficina de correos entre remitente y destinatario: toma tu carta, la guarda y la conserva hasta que el destinatario la recoge — así no se pierde nada si no está.

En el medio está el **message broker** — software como **RabbitMQ** o **Apache Kafka** que recibe mensajes, los almacena de forma fiable y los entrega a los consumers. Es la oficina de correos del sistema. Su fiabilidad es el punto clave: aunque todos los consumers estén caídos, el broker guarda los mensajes hasta que alguien esté listo para procesarlos, así que el trabajo queda aparcado, no perdido.

_Diagram: El broker recibe y almacena los mensajes de forma fiable. El consumer está caído — los mensajes esperan en lugar de desaparecer._

#### Message Broker (broker)

- **Problema:** Los mensajes necesitan un lugar seguro donde vivir hasta que alguien los tome.
- **Idea:** Un software dedicado recibe, almacena y entrega mensajes — la oficina de correos del sistema.
- **Ejemplo:** **RabbitMQ**, **Apache Kafka**.
- **Coste:** Un sistema más que ejecutar y mantener.
- **Relaciones:** Guarda la **Message Queue**; **Resilience** se apoya en su fiabilidad.

### Competing Consumers — añade consumers para ir más rápido

> Cuando las comandas se acumulan, pones más cocineros en la línea — cada uno toma la siguiente comanda y el atraso se despeja más rápido sin cambiar cómo entran los pedidos.

Como los consumers simplemente toman el siguiente mensaje, puedes ejecutar **muchos en paralelo** sobre una sola queue — este es el patrón **Competing Consumers**. ¿Crece el atraso? Añade más workers y se reparten la carga automáticamente — cada uno agarra un mensaje distinto. Esta es una de las grandes fortalezas de una queue: escalas la parte lenta de forma independiente añadiendo consumers, sin tocar a los producers ni la queue.

_Diagram: Tres workers en una queue: cada uno toma su propio mensaje. Añade un tercero — el atraso se derrite más rápido._

#### Competing Consumers (worker pool (grupo de workers))

- **Problema:** Un solo worker no da abasto; el atraso crece.
- **Idea:** Varios consumers leen una queue; cada mensaje va a uno de ellos.
- **Ejemplo:** Antes de una rebaja — de dos workers de redimensionado de fotos a diez.
- **Coste:** El procesamiento en paralelo rompe el orden — ver **Message Ordering**.
- **Relaciones:** La base de **Independent Scaling**; funciona con mensajes **Command**.

> **La pregunta de los roles:** «¿Quién produce estos mensajes, quién los consume, y podría despejar un atraso simplemente añadiendo más consumers a la misma queue?»

> Los producers crean mensajes, los consumers los procesan y un broker los guarda con seguridad en el medio. ¿Necesitas más rendimiento? Añade consumers — se reparten la queue automáticamente.

## 4. Eventos frente a comandos

Un mensaje puede ser dos cosas muy distintas: una orden de hacer algo, o un anuncio de que algo ocurrió. La segunda cambia en silencio cómo diseñas sistemas enteros.

### Command — un comando le dice a un worker que haga una tarea

> Una orden de trabajo entregada a un departamento concreto: «redimensiona esta imagen». Nombra la tarea, espera que exactamente un equipo la haga, y ahí termina todo.

Un mensaje **command** es una instrucción directa dirigida a un consumer: «envía este correo», «procesa este pago». Es la queue usada como lista de tareas — el producer sabe qué debe ocurrir y entrega la tarea para que se haga una vez, por quien la tome. Este es el uso más simple de una queue: delegar trabajo concreto para hacerlo más tarde, exactamente una vez.

_Diagram: El comando SendEmail: «haz esto». Exactamente un consumer lo toma._

#### Command (command message (mensaje de comando))

- **Qué es:** Un mensaje-orden: «haz esto». Se nombra con un verbo.
- **Cómo funciona:** El producer sabe qué debe ocurrir; un consumer hace la tarea.
- **Ejemplo:** `SendEmail`, `ProcessPayment`, `ResizeImage`.
- **Trampa:** El producer sigue sabiendo qué trabajo hace falta — queda algo de acoplamiento.
- **Relaciones:** Lo opuesto a **Event**; a menudo lo despachan **Competing Consumers**.

### Event — un evento anuncia que algo ocurrió

> Un anuncio para toda la empresa en un tablón: «acaba de registrarse un nuevo cliente». No le dice a nadie qué hacer — quien le interese reacciona a su manera.

Un **event** es distinto: enuncia un hecho del pasado — «pedido realizado», «usuario registrado» — sin decir quién debe hacer qué. El producer solo lo anuncia y no sabe ni le importa quién escucha. Quizá nadie reaccione; quizá cinco servicios lo hagan. Esto invierte la relación: en lugar de ordenar a un worker concreto, difundes que algo es cierto y dejas que los interesados decidan.

_Diagram: El evento OrderPlaced: «esto ocurrió». El producer no sabe quién escucha._

#### Event (event message (mensaje de evento))

- **Qué es:** Un hecho del pasado: «esto ocurrió». Se nombra en pasado.
- **Cómo funciona:** El producer lo anuncia y no sabe quién escucha: cero, uno o cinco servicios.
- **Ejemplo:** `OrderPlaced`, `UserRegistered`.
- **Trampa:** Es más difícil ver qué pasará al final — las reacciones están repartidas entre servicios.
- **Relaciones:** Lo opuesto a **Command**; se entrega vía **Pub/Sub**; la base de **Event-driven**.

### Publish/Subscribe — un evento, muchas reacciones

> Un periódico impreso una vez y entregado a cada suscriptor, y cada uno lo lee por sus propias razones — aficionado al deporte, inversor, fan de los crucigramas — del mismo ejemplar.

Este modelo de difusión es **publish/subscribe** (pub/sub): un producer **publica** un evento en un **topic**, y cada consumer interesado se **suscribe** y recibe su propia copia. Un solo evento «pedido realizado» puede activar a la vez el servicio de correo, el de analítica y el de envíos — esto es **fan-out**. El publicador ni siquiera sabe que existen. Se pueden añadir nuevas reacciones más tarde sin tocar al publicador.

_Diagram: Un evento en un topic — y cada suscriptor recibe su propia copia: eso es fan-out._

#### Publish/Subscribe (pub/sub, topic, fan-out)

- **Problema:** Un evento le importa a muchos servicios, y la lista no deja de crecer.
- **Idea:** Publicar en un **topic**; cada suscriptor recibe **su propia copia** (**fan-out**).
- **Ejemplo:** «Pedido realizado» → correo, analítica y envíos reaccionan a la vez.
- **Coste:** Cada copia se procesa por separado; la cadena completa de reacciones es difícil de ver.
- **Relaciones:** Entrega **Events**; **Event-driven Architecture** se construye sobre él.

### Event-driven Architecture — los eventos desacoplan quién conoce a quién

> Añadir un suscriptor nuevo al periódico no cambia nada en cómo se escribe el periódico — el publicador nunca necesita saber quién lee.

Este es el poder profundo del diseño **event-driven**: el producer de un evento queda totalmente desacoplado de todos los que reaccionan a él. Para añadir una función nueva que responda a «pedido realizado», solo suscribes un consumer nuevo — sin cambiar el servicio de pedidos. Los sistemas construidos así crecen añadiendo oyentes, no editando lo que se escucha. Así evolucionan los sistemas grandes sin que todo dependa de todo.

_Diagram: Una función nueva es un suscriptor nuevo. El servicio de pedidos no cambia._

#### Event-driven Architecture (EDA)

- **Problema:** Cada función nueva obliga a editar el servicio donde «ocurre todo».
- **Idea:** Los servicios anuncian eventos; las funciones se añaden como oyentes nuevos.
- **Ejemplo:** Dar puntos de fidelidad por pedido — suscribir un servicio nuevo a «pedido realizado».
- **Coste:** **Eventual Consistency**, y una petición que salta entre mensajes es más difícil de depurar.
- **Relaciones:** Construida sobre **Event** y **Pub/Sub**; da **Independent Scaling**.

> **La pregunta de pub/sub:** «¿Estoy ordenando a un worker concreto que haga una tarea — o anunciando que algo ocurrió y dejando que cualquier número de servicios reaccione por su cuenta?»

> Un command le dice a un consumer que haga una tarea. Un event anuncia un hecho y deja que cualquiera reaccione — y pub/sub reparte un evento a muchos, desacoplando quién conoce a quién.

## 5. Por qué es poderoso

Las queues añaden piezas móviles, así que tienen que ganárselo. Lo hacen comprando tres cosas difíciles de conseguir de otra forma: resiliencia, manejo suave de picos y escalado independiente.

### Resilience — un consumer caído solo retrasa el trabajo

> Si la cocina cierra una hora, las comandas simplemente esperan en el riel — cuando reabre, los cocineros despachan el atraso. No se pierde ningún pedido.

Como el broker guarda los mensajes, que un consumer se caiga no pierde trabajo — los mensajes esperan hasta que vuelva y entonces se procesan. Compáralo con una llamada directa, donde un servicio caído significa un fallo rotundo. La queue convierte «el servicio está caído» de un error duro en un retraso temporal. Esta **resilience** — el trabajo sobrevive a un fallo y se reanuda — suele ser la razón más importante por la que los equipos recurren a una queue.

_Diagram: Arriba: B está caído — la petición falla. Abajo: B está caído — el trabajo espera en la queue y se reanuda cuando B vuelve._

#### Resilience (fault tolerance (tolerancia a fallos))

- **Problema:** Con una llamada directa, un servicio caído significa un error para todos.
- **Idea:** El broker guarda los mensajes; un fallo se convierte en un retraso.
- **Ejemplo:** El worker de correo se cae una hora — los correos esperan en la queue y salen tras el reinicio.
- **Coste:** Mientras el consumer está caído, el trabajo se acumula y se hace tarde.
- **Relaciones:** Cura **Failure Propagation**; se apoya en la fiabilidad del **Broker**.

### Load Leveling — absorbe los picos

> Un embalse entre una crecida repentina y un pueblo: la oleada entra en el embalse, que suelta el agua a un ritmo constante y seguro río abajo.

Cuando llega de golpe una avalancha de peticiones — una rebaja, un momento viral — una queue te permite **nivelar la carga**: el pico llena la queue y los consumers la vacían a su propio ritmo constante. El sistema lento de más abajo nunca ve el pico, solo un flujo manejable y parejo. A la presión que genera el atraso se la llama **backpressure**. Sin una queue, el mismo pico golpearía directamente al sistema y probablemente lo derribaría.

_Diagram: Un pico de peticiones llena la queue, y los consumers la vacían de forma constante. El sistema de más abajo nunca ve el pico._

#### Queue-Based Load Leveling (load leveling, backpressure)

- **Problema:** Un pico de tráfico golpea directamente a un sistema lento y lo derriba.
- **Idea:** El pico llena la queue; los consumers la despachan a su propio ritmo.
- **Ejemplo:** Una rebaja: miles de pedidos por minuto se procesan como un flujo constante.
- **Coste:** El atraso crece y el trabajo se hace tarde (**backpressure**) — vigila la longitud de la queue.
- **Relaciones:** Se apoya en **Temporal Decoupling**; los **Competing Consumers** despejan el atraso.

### Independent Scaling — escala y evoluciona cada lado por su cuenta

> Puedes contratar más cocineros, cambiar el equipo de la cocina o añadir una estación nueva — todo sin cambiar cómo toman los pedidos los camareros, porque solo tocan el riel de comandas.

El desacoplamiento significa que cada lado puede cambiar **de forma independiente** (independent scaling). Sube o baja los consumers según la demanda; reescribe un consumer en otro lenguaje; añade un consumer nuevo que reaccione a eventos existentes — todo sin tocar a los producers. La queue es una costura estable entre las partes del sistema, y las costuras estables son lo que permite que un sistema grande crezca y cambie por piezas en lugar de todo a la vez.

_Diagram: La queue es una costura estable. A la derecha puedes escalar, reescribir y añadir — nada a la izquierda cambia._

#### Independent Scaling (independent scaling and evolution (escalado y evolución independientes))

- **Problema:** Cambiar una parte obliga a tocarlas todas.
- **Idea:** La queue es una costura estable; cada lado cambia por su cuenta.
- **Ejemplo:** Un worker se reescribe en otro lenguaje — los producers ni se enteran.
- **Coste:** El formato del mensaje se vuelve un contrato — cámbialo con cuidado.
- **Relaciones:** Lo entregan **Competing Consumers** y **Event-driven Architecture**.

> **La pregunta del beneficio:** «¿Estoy recurriendo a una queue para obtener resiliencia, absorción de picos o escalado independiente — un beneficio concreto que justifique la pieza móvil extra?»

> Las queues compran resiliencia (el trabajo sobrevive a una caída), load leveling (los picos se absorben) y escalado independiente — beneficios que una llamada directa simplemente no puede darte.

## 6. Las nuevas partes difíciles

La mensajería asíncrona resuelve problemas reales y crea otros nuevos. Ninguno es un obstáculo insalvable, pero fingir que no existen es como los sistemas con queues acaban con errores sutiles y desesperantes.

### At-least-once e Idempotency — los mensajes pueden llegar dos veces

> Para estar seguro, el correo a veces entrega una copia de una carta de la que no está seguro que llegó — mejor dos veces que ninguna, pero ahora podrías actuar dos veces sobre la misma instrucción.

La mayoría de los brokers garantizan entrega **at-least-once** (al menos una vez): prefieren enviar un mensaje dos veces antes que arriesgarse a perderlo, así que un consumer puede recibir ocasionalmente el mismo mensaje más de una vez. Si «cobrar al cliente» se ejecuta dos veces, es un problema real. La solución es la **idempotency**: diseñar el trabajo para que hacerlo dos veces tenga el mismo efecto que hacerlo una (comprobar primero «¿ya está cobrado?»). Asume duplicados; hazlos inofensivos.

_Diagram: El broker envió «cobrar pedido 42» dos veces. El consumer comprueba primero «¿ya está cobrado?» — y simplemente se salta el segundo._

#### Idempotency (at-least-once delivery (entrega al menos una vez))

- **Problema:** Entrega **at-least-once**: el mismo mensaje puede llegar más de una vez.
- **Idea:** Hacer el trabajo de modo que ejecutarlo dos veces tenga el mismo efecto que una.
- **Ejemplo:** Antes de cobrar, comprobar «¿el pedido 42 ya está cobrado?» — si sí, saltar.
- **Coste:** Necesitas recordar en algún sitio qué ya se ha hecho.
- **Relaciones:** Imprescindible para todo **Consumer**; junto con la **Dead-Letter Queue** hace seguros los reintentos.

### Message Ordering — el orden no está garantizado

> Dos cartas enviadas en secuencia pueden llegar en cualquier orden — así que si el paso dos aparece antes que el paso uno, el destinatario se confunde.

Con muchos mensajes y muchos consumers en paralelo, los mensajes no se procesan necesariamente en el orden en que se enviaron. Si «actualizar dirección» y «eliminar cuenta» llegan desordenados, sale un disparate. Algunos sistemas conservan el orden dentro de una categoría a cierto coste; a menudo es más barato diseñar un trabajo que no dependa de un orden estricto. Sea como sea, **nunca asumas orden** a menos que lo hayas dispuesto expresamente.

_Diagram: Se envió «actualizar dirección» y luego «eliminar cuenta». Se procesaron al revés — y ahora actualizas una cuenta que ya no existe._

#### Message Ordering (ordering guarantees (garantías de orden))

- **Problema:** Los consumers en paralelo no procesan los mensajes en el orden en que se enviaron.
- **Idea:** No confiar en el orden — o disponerlo explícitamente dentro de una categoría.
- **Ejemplo:** «Eliminar cuenta» se procesó antes que «actualizar dirección» — el resultado es un disparate.
- **Coste:** El orden estricto exige esfuerzo y estorba al paralelismo.
- **Relaciones:** El precio de **Competing Consumers**; vecino de **Eventual Consistency**.

### Eventual Consistency — el resultado es consistente con el tiempo

> Un anuncio que se difunde por una oficina: durante unos momentos unos lo saben y otros no, hasta que la noticia llega a todos y vuelven a coincidir.

Como las reacciones ocurren de forma asíncrona, el sistema es **eventualmente consistente**: justo después de un evento, distintas partes pueden discrepar brevemente — el pedido existe pero la analítica aún no lo ha contado. Se pone al día en instantes, pero la «consistencia instantánea en todas partes» desaparece. Diseñas alrededor de esta brecha, mostrando a los usuarios estados intermedios razonables, en lugar de asumir que todas las partes se actualizan en el mismo instante.

_Diagram: El pedido ya existe, pero la analítica todavía no lo ha contado. Una brecha corta — y luego todos vuelven a coincidir._

#### Eventual Consistency (consistent in the end (consistente al final))

- **Problema:** Justo después de un evento, partes del sistema ven brevemente cosas distintas.
- **Idea:** Aceptar la brecha: cada parte se pone al día y coincide — un poco después.
- **Ejemplo:** El pedido se crea pero aún no está en el informe; un momento después, sí.
- **Coste:** Hay que diseñar estados intermedios para el usuario («procesando…»).
- **Relaciones:** Consecuencia de **Asynchronous Processing** y **Event-driven Architecture**.

### Dead-Letter Queue — un mensaje envenenado necesita adónde ir

> Una carta con la que nadie puede hacer nada — borrosa, imposible — no puede reintentarse para siempre atascando la fila. Se aparta en una bandeja especial para que alguien la revise.

Algunos mensajes nunca pueden procesarse con éxito — están mal formados o se refieren a datos que ya no existen. Si se dejan, un **poison message** (mensaje envenenado) así se reintenta para siempre y bloquea la queue. La respuesta estándar es una **dead-letter queue**: tras unos cuantos intentos fallidos, el mensaje se aparta a una queue separada para inspeccionarlo, de modo que deja de envenenar el flujo. Planifica los mensajes que fallan, o un solo mensaje malo detiene todo lo que hay detrás.

_Diagram: Los mensajes normales pasan. El envenenado, tras tres intentos, pasa a la dead-letter queue — para que una persona lo inspeccione._

#### Dead-Letter Queue (DLQ)

- **Problema:** Un **poison message** falla siempre, se reintenta sin fin y bloquea la queue.
- **Idea:** Tras unos cuantos fallos, apartar el mensaje a una queue separada para revisarlo.
- **Ejemplo:** Un mensaje sobre un usuario eliminado va a la DLQ tras tres intentos.
- **Coste:** Alguien tiene que vigilar la DLQ, o se vuelve un cementerio de trabajo perdido.
- **Relaciones:** Los reintentos solo son seguros con **Idempotency**; mantiene el flujo en marcha para **Resilience**.

> **La pregunta de las partes difíciles:** «¿He hecho este trabajo seguro para ejecutarse dos veces, libre de supuestos de orden, tolerante a una breve inconsistencia — y adónde van los mensajes cuando no se pueden procesar?»

> La mensajería asíncrona trae duplicados (se manejan con idempotency), orden no garantizado, eventual consistency y mensajes que fallan (usa una dead-letter queue). Planifica los cuatro.

## 7. Usarlo bien

Una queue es una herramienta potente, no una opción por defecto. La habilidad está en recurrir a ella cuando desacoplar de verdad compensa, y mantener la llamada directa cuando la simplicidad vale más.

### Queue vs Direct Call — usa una queue cuando esperar es el problema

> Tomas un número y te vas por un servicio lento que recogerás después — pero para un sí o un no rápido simplemente preguntas en el mostrador, porque sacar un ticket sería más absurdo que esperar.

Recurre a una queue cuando el trabajo es **lento, con picos o no urgente**, cuando quieres que el que llama siga siendo rápido, o cuando varios servicios deben reaccionar a una misma cosa. Mantén una **llamada directa** cuando necesitas una respuesta inmediata para continuar — una consulta de precio, una comprobación de permisos — porque ahí la simplicidad y el resultado instantáneo valen más que el desacoplamiento. Ajusta la herramienta a si esperar es de verdad el problema.

_Diagram: Una pregunta: ¿necesitas la respuesta para continuar? Sí — una llamada directa. No — una queue._

#### Queue vs Direct Call (how to choose (cómo elegir))

- **Pregunta:** ¿El que llama necesita la respuesta para continuar?
- **Queue:** El trabajo es lento, con picos, no urgente o lo necesitan muchos (fan-out).
- **Llamada directa:** Necesitas una respuesta instantánea: una consulta de precio, una comprobación de permisos.
- **Coste de la queue:** Un broker, duplicados, orden, eventual consistency, trazado más difícil.
- **Relaciones:** La elección entre **Synchronous Call** y **Message Queue**.

### No recurras a ella por reflejo

> Instalar una sala de correo completa con sistema de clasificación para pasarle una nota a la persona del escritorio de al lado — la maquinaria cuesta ya más que el problema que resuelve.

Las queues añaden complejidad real: un broker que ejecutar, duplicados y orden que manejar, eventual consistency alrededor de la cual diseñar, y más dificultad para trazar una petición que ahora salta entre mensajes. Para un sistema simple con una llamada rápida entre dos partes, esa carga no compensa. Añade una queue cuando un beneficio concreto — resiliencia, escala, desacoplamiento — justifique el coste, no porque lo event-driven suene avanzado.

### Los conceptos están conectados

> Una cinta transportadora: de un dolor a una cura — y la cura tiene sus propios beneficios y sus propios efectos secundarios.

Esta es la imagen completa. El dolor de la **synchronous call** lo cura una **message queue**, guardada por un **broker**. Por la queue viajan **commands** (a un consumer) y **events** (a muchos, vía **pub/sub**). Eso compra los **beneficios** — resiliencia, load leveling, escalado — y trae las **partes difíciles**: duplicados, orden, eventual consistency y la DLQ.

_Diagram: Los vínculos principales entre los conceptos del curso: de la llamada directa a la queue, sus beneficios y su precio._

#### Antes de añadir una queue

- **¿Es esperar el problema** — el trabajo es lo bastante lento, con picos o no urgente como para desacoplarlo?
- **Command o event** — ¿un worker haciendo una tarea, o muchos servicios reaccionando a un hecho?
- **¿Es idempotente el trabajo** — seguro de ejecutar dos veces, ya que los mensajes pueden llegar dos veces?
- **¿Asume orden**, y lo he dispuesto o lo he eliminado del diseño?
- **¿Puede el sistema tolerar** una breve inconsistencia eventual?
- **Adónde van los mensajes fallidos** — ¿hay una dead-letter queue?

#### Señales de que usas bien las queues

- Pones en queue el trabajo **lento, con picos y no urgente** y mantienes las **llamadas directas** para respuestas instantáneas.
- Tus consumers son **idempotentes**, así que un mensaje duplicado no hace daño.
- **No asumes orden** a menos que lo hayas dispuesto explícitamente.
- Diseñas para **eventual consistency** en lugar de esperar un acuerdo instantáneo.
- Los mensajes fallidos acaban en una **dead-letter queue** en lugar de atascar la fila.

## Resumen: los 21 conceptos

### El problema de la llamada directa

- **Synchronous Call** (request–response): Llamar y esperar. Simple, pero acopla los servicios en el tiempo.
- **Failure Propagation** (cascading failure): Un servicio caído arrastra a todos los que lo llaman.
- **Background Work** (background jobs): Trabajo que el usuario no debería esperar: correos, facturas, fotos.

### La queue

- **Message Queue** (queue): Deja un mensaje y sigue; el receptor lo recoge por su cuenta.
- **Temporal Decoupling** (buffer in time): Un búfer: los lados no tienen que funcionar en el mismo momento.
- **Asynchronous Processing** (async): No esperar el resultado; el desenlace ocurre después.

### Roles

- **Producer / Consumer** (publisher / worker): Uno escribe mensajes, el otro los procesa; solo conocen la queue.
- **Message Broker** (broker): Software que almacena y entrega mensajes de forma fiable: RabbitMQ, Kafka.
- **Competing Consumers** (worker pool): Muchos workers en una queue se reparten la carga.

### Comandos y eventos

- **Command** (haz esto): «Haz esto» — exactamente un consumer lo hace.
- **Event** (esto ocurrió): «Esto ocurrió» — cualquiera reacciona, o nadie.
- **Publish/Subscribe** (pub/sub, topic, fan-out): Un evento en un topic — cada suscriptor recibe su propia copia.
- **Event-driven Architecture** (EDA): Las funciones se añaden como oyentes nuevos, no editando al publicador.

### Beneficios

- **Resilience** (fault tolerance): La caída de un consumer es un retraso, no trabajo perdido.
- **Queue-Based Load Leveling** (load leveling, backpressure): Un pico llena la queue; los consumers la vacían de forma constante.
- **Independent Scaling** (independent evolution): Cada lado escala y cambia por su cuenta.

### Partes difíciles

- **Idempotency** (at-least-once): Los duplicados ocurren — hazlos inofensivos.
- **Message Ordering** (ordering guarantees): El orden no está garantizado a menos que lo dispongas.
- **Eventual Consistency** (consistent in the end): Partes del sistema discrepan brevemente y luego se ponen al día.
- **Dead-Letter Queue** (DLQ): Una queue aparte para los mensajes que fallan una y otra vez.

### Elegir

- **Queue vs Direct Call** (cómo elegir): Necesitas la respuesta para continuar — llamada directa; si no — una queue.

> Las queues son deliberadas: recurre a una cuando desacoplar en el tiempo compra resiliencia, escala o fan-out — y mantén la llamada directa cuando una respuesta instantánea importa más que todo eso.

Fin del curso exprés · 7 capítulos · 21 conceptos

Ahora viene la práctica: toma una cosa lenta que tu app hace en línea — enviar un correo, generar un informe — y muévela detrás de una queue, para que el usuario reciba una respuesta instantánea y un worker haga la parte lenta después. Luego haz que ese worker sea seguro de ejecutar dos veces. El patrón encaja en el momento en que ves que la respuesta se vuelve rápida y el trabajo se sigue haciendo. Pero quédate con una idea por encima de las demás: el cambio es de llamar y esperar a dejar un mensaje y continuar. Desacopla el trabajo en el tiempo y tu sistema se vuelve más rápido, más resistente y más fácil de hacer crecer — al precio de pensar en eventos en lugar de comandos.
