Cuando un sistema tiene que decirle algo a otro, la solución obvia —llamarlo directo y esperar la respuesta— es la más frágil. Si el otro está caído, lento o saturado, tu sistema se cae con él. La mensajería asíncrona rompe ese acoplamiento con un intermediario que recibe y entrega. Y ahí aparecen dos familias que se confunden todo el tiempo: las colas y los streams. Se parecen por fuera; por dentro contestan preguntas distintas.
El problema: comunicarse sin acoplarse
En cualquier arquitectura, los sistemas necesitan intercambiar información sin bloquearse ni depender de que el otro esté disponible en ese instante exacto. Si el servicio A tiene que esperar a que el servicio B conteste, la disponibilidad de A queda atada a la de B.
La mensajería asíncrona pone un intermediario en medio: el productor entrega su mensaje y sigue, sin esperar a que el consumidor lo procese. El intermediario recibe, guarda y entrega. Así los dos sistemas se desacoplan en el tiempo.
Hay dos familias de intermediario: las colas (queues) y los logs / streams. Elegir bien entre ellas es la decisión de arquitectura que este artículo desarma.
La cola (message queue)
Una cola es exactamente lo que suena: una fila. Un productor pone mensajes por un extremo; un consumidor los saca por el otro.
- El productor deja un mensaje en la cola y continúa con su trabajo. No espera respuesta.
- El mensaje queda almacenado en la cola hasta que alguien lo tome. Si el consumidor está caído, el mensaje espera.
- Un consumidor saca los mensajes de la cola, uno a uno, y los procesa.
- Al consumirse y confirmarse, el mensaje se elimina de la cola: ya cumplió su función y desaparece.
Ese modelo sirve para tres cosas: repartir trabajo (varios consumidores se turnan mensajes de la misma cola, escalando el procesamiento), garantizar la entrega (el mensaje no se pierde: espera hasta ser procesado y confirmado) y desacoplar productor de consumidor. Ejemplos clásicos: IBM MQ y RabbitMQ.
El stream (log distribuido)
Un stream funciona con otra lógica. En vez de una fila de la que sacas y borras, es un registro que solo crece. El caso de referencia es Apache Kafka.
- Los eventos se añaden al final de un log particionado y replicado. No se insertan en medio ni se sacan: solo se agregan.
- Los eventos se retienen durante un tiempo configurado y no se borran al leerse. Leer no consume.
- Varios consumidores leen de forma independiente, cada uno a su propio ritmo, marcando por dónde va con su offset (su posición en el log).
- Como los eventos siguen ahí, un consumidor puede volver a leer desde el pasado: el flujo es reproducible.
Ese diseño está pensado para alto volumen y para que muchos sistemas distintos consuman el mismo flujo sin pisarse. Nadie "vacía" el stream: es una fuente de verdad durable de lo que fue pasando, que cada lector recorre a su ritmo.
La diferencia que importa
Reducido a lo esencial, la distinción es una sola y lo cambia todo:
- Cola = "consumir y desaparece". El trabajo se reparte una vez entre los consumidores; cada mensaje lo procesa uno, y al procesarse se va.
- Stream = "historia durable y reproducible". El mismo evento lo pueden leer muchos lectores, cada uno independiente, y se puede releer desde el pasado.
Pensar que la diferencia es velocidad vs lentitud. No lo es. No se trata de que uno sea rápido y el otro lento: son modelos distintos de mensajería. Uno reparte y borra; el otro retiene y reproduce. Elegir por "cuál es más rápido" es elegir mal la pregunta.
MQ y Kafka, lado a lado
| Característica | MQ (cola) | Kafka (stream) |
|---|---|---|
| Modelo | Cola | Log distribuido |
| ¿El mensaje se borra al leerse? | Sí | No, se retiene |
| ¿Cuántos consumen el mismo mensaje? | Uno | Muchos, independientes |
| ¿Reproducible? | No | Sí |
| Fortaleza | Entrega transaccional garantizada | Streaming de alto volumen |
| Ejemplos | IBM MQ, RabbitMQ | Apache Kafka |
Errores comunes
"Kafka reemplaza a MQ." No. Resuelven necesidades distintas. Kafka no es una cola tradicional (retiene los eventos y los reproduce), y una cola no es un log de eventos (entrega una vez y borra). Elegir el equivocado no da un error inmediato: se paga después, en complejidad.
- Creer que "todo necesita Kafka". Kafka es potente, pero suma operación: particiones, offsets, retención, clúster. Para repartir trabajo con entrega garantizada, una cola es más simple y más adecuada.
- Confundir un mensaje con un evento. Un mensaje de cola es una instrucción para que alguien haga algo (y luego desaparece). Un evento de stream es un hecho que ocurrió y queda registrado para quien quiera leerlo. No son intercambiables.
- Forzar el modelo equivocado al problema. Usar una cola donde necesitas releer historia, o un stream donde necesitas reparto exclusivo con confirmación, te deja peleando contra la herramienta.
El ángulo banca
En banca esta distinción no es teórica: define qué tecnología toca cada flujo.
IBM MQ es el estándar de facto para la mensajería transaccional core. Una instrucción de pago no se puede perder ni duplicar: tiene que llegar, exactamente una vez, y confirmarse. La entrega garantizada de una cola —el mensaje espera hasta procesarse y recién ahí desaparece— es exactamente esa propiedad. Por eso el motor de pagos, la transferencia entre cuentas y la mensajería entre sistemas críticos se mueven sobre colas.
Kafka encaja en el otro lado: flujos de eventos, analítica en tiempo real y pipelines de detección de fraude. Ahí quieres que muchos sistemas —scoring, monitoreo, tableros, reglas— lean el mismo flujo de eventos de forma independiente, a su ritmo, y puedan reprocesar el historial cuando cambia un modelo. Eso es exactamente lo que un log distribuido hace bien.
No es MQ o Kafka. Los dos conviven en el mismo banco, cada uno donde brilla. La pregunta no es cuál gana; es qué problema tienes: repartir trabajo con entrega garantizada, o transmitir una historia de eventos reproducible a muchos lectores. Sabiendo eso, la elección deja de ser una moda y vuelve a ser ingeniería.