MQTT vs Kafka es una de las preguntas de arquitectura más habituales en IoT, y la respuesta honesta es que resuelven dos mitades distintas del problema. MQTT saca los datos de miles de dispositivos pequeños y con conexión intermitente; Kafka almacena, reproduce y procesa streams de eventos de gran volumen dentro de tu plataforma de datos. Esta guía compara ambos, explica dónde falla cada uno y muestra un patrón funcional para mover datos de un broker MQTT a Kafka con un servicio consumidor que tú controlas.
Dos herramientas para dos trabajos
MQTT es un protocolo publish/subscribe ligero. Los dispositivos abren una única conexión TCP con un broker, publican en topics jerárquicos y se suscriben a los topics que necesitan. El broker enruta los mensajes en tiempo real, guarda el último valor retenido de cada topic, almacena en búfer los mensajes QoS 1 y 2 para las sesiones persistentes desconectadas y publica un Last Will cuando un dispositivo se cae. Está diseñado para clientes con recursos limitados y redes poco fiables. Si estás empezando, qué hace un broker MQTT es un buen punto de partida.
Apache Kafka es un commit log distribuido de solo anexado. Los productores escriben registros en topics particionados, Kafka los almacena de forma duradera durante un periodo de retención configurable y los grupos de consumidores leen a su propio ritmo y pueden rebobinar para reprocesar el historial. Está diseñado para servicios backend en redes fiables que mueven grandes volúmenes de eventos entre sistemas, con herramientas del ecosistema para procesamiento de streams y conectores hacia bases de datos y data lakes.
La confusión viene del vocabulario compartido. Ambos tienen "topics", ambos tienen productores y consumidores, y a ambos se les llama sistemas de mensajería. Pero un topic MQTT es una dirección de enrutamiento que puede crearse sobre la marcha con miles de variaciones en sus niveles, mientras que un topic de Kafka es un log duradero y particionado que se aprovisiona de forma deliberada.
MQTT vs Kafka de un vistazo
| Aspecto | MQTT | Apache Kafka |
|---|---|---|
| Propósito principal | Conectividad de dispositivos y enrutamiento en tiempo real | Log de eventos duradero y procesamiento de streams |
| Clientes típicos | Microcontroladores, gateways, apps móviles, navegadores | Servicios backend, procesadores de streams, conectores |
| Conexiones | Muchísimas conexiones, la mayoría inactivas | Menos conexiones, de alto rendimiento |
| Topics | Jerárquicos, dinámicos, suscripciones con comodines | Nombres planos, aprovisionados, particionados |
| Almacenamiento | Último valor retenido por topic, colas de sesión | Historial completo durante el periodo de retención |
| Reproducción | No (solo el último valor retenido) | Sí, los consumidores pueden saltar a cualquier offset |
| Entrega | QoS 0, 1, 2 por mensaje | Acks por productor, offsets por grupo de consumidores |
| Orden | Por topic y por sesión de cliente | Por partición |
| Huella del cliente | Kilobytes, funciona en un ESP32 | Librerías cliente pesadas, JVM o librdkafka |
| Supuestos de red | Con pérdidas, alta latencia, NAT, celular | Red fiable de centro de datos o nube |
| Funciones para dispositivos | Keep alive, Last Will, estado retenido | Ninguna |
| Soporte en navegador | MQTT sobre WebSocket | No directamente |
Por qué los dispositivos no deberían hablar directamente con Kafka
Técnicamente es posible ejecutar un productor de Kafka en un gateway, pero con flotas de dispositivos rara vez acaba bien:
- Peso del cliente. Los clientes de Kafka necesitan mucha más memoria y CPU de la que tiene un microcontrolador, y asumen conexiones estables con varios brokers.
- Modelo de conexión. Kafka está pensado para un número moderado de productores muy activos, no para decenas de miles de dispositivos que envían una lectura cada pocos segundos por enlaces inestables.
- Sin semántica de dispositivo. No hay Last Will, ni detección de desconexión basada en keep alive, ni último valor conocido retenido por dispositivo.
- Comandos hacia los dispositivos. Los consumidores de Kafka hacen pull; no hay una forma natural de enviar un comando a un dispositivo concreto detrás de un NAT.
- Superficie de seguridad. Exponer los listeners de Kafka a internet para los dispositivos implica gestionar credenciales y ACL por dispositivo en una infraestructura diseñada para vivir dentro de una red privada.
Por qué MQTT por sí solo no es una plataforma de datos
MQTT tiene las carencias opuestas. Un broker enruta mensajes; no guarda historial. Si tu proceso de analítica está caído una hora, las lecturas que se perdió desaparecen salvo que una sesión persistente las haya retenido, y las colas de sesión no son un almacenamiento a largo plazo. No puedes reproducir los datos de la semana pasada con un algoritmo nuevo, ni unir streams o calcular ventanas dentro del broker. Ese es justo el trabajo en el que destacan Kafka y su ecosistema de procesamiento de streams.
El patrón: MQTT en el edge, Kafka en el núcleo
La arquitectura en la que acaban coincidiendo la mayoría de los equipos es esta:
- Los dispositivos y gateways publican en un broker MQTT, por ejemplo en
connectmq/factory1/production/line1/cnc1/telemetry. - Uno o varios servicios consumidores se suscriben a los filtros de topic relevantes.
- Esos servicios validan, enriquecen y asignan una clave a cada mensaje, y luego lo producen en un topic de Kafka como
iot.telemetry, normalmente con el ID del dispositivo como clave para mantener el orden por dispositivo dentro de una partición. - Los procesadores de streams, sinks y herramientas de analítica leen de Kafka.
- Los comandos fluyen en sentido contrario: un servicio consume un topic de comandos de Kafka y publica en el topic de comandos MQTT del dispositivo.
ConnectMQ no incluye un bridge a Kafka integrado, así que el enlace entre ambos es siempre un componente que ejecutas tú: o bien tu propio servicio consumidor, como el que se muestra a continuación, o bien un conector MQTT source estándar para Kafka Connect configurado para suscribirse a tu broker como un cliente MQTT normal. Ambos enfoques tratan el broker como un endpoint MQTT estándar, lo que mantiene la integración portable.
Crea un servicio consumidor de MQTT a Kafka
El siguiente servicio en Python se suscribe a ConnectMQ con una suscripción compartida, de modo que puedes ejecutar varias instancias y dejar que el broker reparta la carga entre ellas, y produce cada mensaje en Kafka con confluent-kafka. Las suscripciones compartidas requieren MQTT 5 y están disponibles en el plan Serverless (Paid) y superiores.
pip install "paho-mqtt>=2.0" confluent-kafka
import json
import ssl
import signal
import sys
import paho.mqtt.client as mqtt
from confluent_kafka import Producer
MQTT_HOST = "broker.connectmq.com"
MQTT_FILTER = "$share/kafka-bridge/connectmq/factory1/+/+/+/telemetry"
KAFKA_TOPIC = "iot.telemetry"
producer = Producer({
"bootstrap.servers": "localhost:9092",
"enable.idempotence": True,
"linger.ms": 20,
})
def delivery_report(err, record):
if err is not None:
print(f"Kafka delivery failed for key {record.key()}: {err}")
def on_connect(client, userdata, flags, reason_code, properties):
print("MQTT connected:", reason_code)
client.subscribe(MQTT_FILTER, qos=1)
def on_message(client, userdata, msg):
try:
payload = json.loads(msg.payload)
except json.JSONDecodeError:
print("skipping non-JSON payload on", msg.topic)
return
levels = msg.topic.split("/")
device_id = levels[-2] # p. ej. cnc1
record = {"topic": msg.topic, "device": device_id, "data": payload}
producer.produce(KAFKA_TOPIC, key=device_id,
value=json.dumps(record), callback=delivery_report)
producer.poll(0)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id="YOUR_CLIENT_ID", protocol=mqtt.MQTTv5)
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set(cert_reqs=ssl.CERT_REQUIRED)
client.on_connect = on_connect
client.on_message = on_message
def shutdown(*_):
client.disconnect()
producer.flush(10)
sys.exit(0)
signal.signal(signal.SIGINT, shutdown)
signal.signal(signal.SIGTERM, shutdown)
client.connect(MQTT_HOST, 8883, keepalive=30)
client.loop_forever()
Algunos detalles de producción importan más que el propio código:
- Contrapresión. Si Kafka no está disponible,
produceacabará lanzandoBufferErrorcuando se llene la cola local. Decide si bloquear, descartar los datos QoS 0 o dejar de confirmar los mensajes MQTT. paho confirma automáticamente los mensajes QoS 1 cuando termina el callback, así que para garantías más fuertes usa la confirmación manual (client.manual_ack_set(True)yclient.ack(msg.mid, msg.qos)tras el callback de entrega de Kafka). - Claves. Usa el ID del dispositivo como clave de Kafka para que las lecturas de cada dispositivo se mantengan ordenadas dentro de una misma partición.
- Idempotencia. QoS 1 puede entregar duplicados. Incluye un ID de mensaje o una marca de tiempo en el payload para que los consumidores posteriores puedan deduplicar.
- Escalado. Añade instancias del servicio; el prefijo
$share/kafka-bridge/hace que el broker reparta los mensajes entre ellas. Da a cada instancia su propio client ID y sus credenciales correspondientes, ya que dos conexiones con el mismo client ID se desconectarían mutuamente. Consulta suscripciones compartidas en MQTT para más detalles.
Para hacer un prototipo sin credenciales, conéctate al puerto 1883 con un client ID único, elimina el prefijo $share/ y usa un prefijo de topic como connectmq/demo/<random-id>/ en el servidor MQTT público gratuito. Trata esos datos como públicos.
Elegir entre ellos, o usar ambos
Usa solo MQTT cuando necesites conectividad de dispositivos en tiempo real, dashboards, alertas y control y comando, y tus necesidades de historial queden cubiertas por una base de datos de series temporales alimentada por un suscriptor. Muchos proyectos nunca necesitan Kafka.
Usa solo Kafka cuando todos los productores sean servicios backend en redes fiables y necesites streams de eventos duraderos y reproducibles entre sistemas.
Usa ambos cuando tengas una flota de dispositivos y una plataforma de datos que necesite reproducción, varios consumidores independientes a distintas velocidades o procesamiento de streams a escala. Mantén la frontera limpia: los topics MQTT modelan dispositivos y activos; los topics de Kafka modelan streams de eventos de negocio.
En el lado de los dispositivos, un broker MQTT gestionado te ahorra operar tú mismo dos sistemas distribuidos. Compara las opciones en la guía de broker MQTT en la nube, lee MQTT vs AMQP si las colas también están en tu lista y repasa los fundamentos en el tutorial de MQTT.
Conecta tus dispositivos a ConnectMQ
Coloca un broker MQTT gestionado delante de tu clúster de Kafka y deja que cada sistema haga lo que mejor sabe hacer. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, conecta algunos dispositivos y luego apunta tu servicio consumidor hacia él para ver cómo llegan los registros a Kafka.
Preguntas frecuentes
¿Puede Kafka sustituir a un broker MQTT?
No para flotas de dispositivos. Kafka carece de clientes ligeros, detección de desconexión basada en keep alive, Last Will y estado retenido, y no está diseñado para enormes cantidades de dispositivos en redes poco fiables.
¿Puede MQTT sustituir a Kafka?
Solo si no necesitas historial duradero, reproducción ni procesamiento de streams. Un broker MQTT enruta mensajes en tiempo real y solo guarda el último valor retenido de cada topic.
¿Cómo llevo los datos de MQTT a Kafka?
Ejecuta un componente que se suscriba al broker como cliente MQTT y produzca en Kafka: tu propio servicio consumidor o un conector MQTT source de Kafka Connect. ConnectMQ no tiene un bridge a Kafka integrado.
¿Debo usar QoS 1 o QoS 0 para el bridge de MQTT a Kafka?
Usa QoS 1 para los datos que no puedes permitirte perder y haz que el procesamiento posterior tolere duplicados. QoS 0 está bien para telemetría de alta frecuencia en la que un hueco ocasional es aceptable.



