MQTT vs HTTP suele ser la primera decisión de protocolo en un proyecto IoT, y equivocarse se nota más tarde en forma de baterías agotadas, dashboards lentos o un servidor sepultado bajo peticiones de sondeo. Esta guía compara ambos en sobrecarga, push frente a sondeo, consumo energético y modelo de conexión, y después te da un script de benchmark para que midas la diferencia en tu propia red en lugar de fiarte de la palabra de nadie.
Dos modelos de comunicación distintos
HTTP es un protocolo de petición/respuesta. Un cliente abre una conexión, envía una petición con un método, una ruta y unas cabeceras, y el servidor responde. El servidor no puede hablar primero. Si un dispositivo necesita saber si le espera un comando nuevo, tiene que preguntar una y otra vez.
MQTT es un protocolo publish/subscribe. Cada cliente mantiene una única conexión TCP de larga duración con un broker, publica mensajes en topics y se suscribe a los topics que le interesan. El broker envía los mensajes coincidentes en el momento en que llegan. Publicadores y suscriptores nunca se dirigen directamente unos a otros, y eso es lo que permite que una lectura de sensor llegue a la vez a un dashboard, a un escritor de base de datos y a un servicio de alertas. Si quieres ver qué hay en medio, lee qué hace un broker MQTT.
Esa única diferencia, quién inicia la conversación, determina casi todas las demás ventajas e inconvenientes que siguen.
MQTT vs HTTP de un vistazo
| Aspecto | HTTP (REST) | MQTT |
|---|---|---|
| Patrón | Petición/respuesta, siempre inicia el cliente | Publish/subscribe a través de un broker |
| Conexión | De corta duración o keep-alive por cada par cliente-servidor | Una conexión TCP persistente por cliente |
| Push del servidor al dispositivo | No nativo (sondeo, long polling, SSE, WebSocket) | Nativo: el broker envía al publicarse |
| Sobrecarga por mensaje | Línea de petición más cabeceras de texto, a menudo cientos de bytes | Cabecera fija mínima de 2 bytes más el topic |
| Fan-out | El emisor debe llamar a cada receptor | El broker entrega a todos los suscriptores coincidentes |
| Garantías de entrega | Reintentos definidos por la aplicación | QoS 0, 1, 2 integrados |
| Detección de desconexión | Se infiere por la ausencia de peticiones | Keep alive y Last Will |
| Último valor conocido | Consultar una API | Mensajes retenidos |
| Herramientas | Universales: navegadores, proxies, CDN, API gateways | Broker más bibliotecas cliente MQTT |
| Lo que mejor hace | CRUD, transferencia de archivos, APIs públicas, llamadas puntuales | Telemetría, comandos, estado en vivo, muchos dispositivos |
Sobrecarga: bytes en la red
Cada petición HTTP lleva una línea de petición, una cabecera Host y, normalmente, tipo de contenido, longitud del contenido, autorización, user agent y más. Todo es texto y todo se vuelve a enviar con cada petición. Para una lectura de sensor de 20 bytes, las cabeceras pueden ser fácilmente diez veces más grandes que los datos.
Un paquete PUBLISH de MQTT tiene una cabecera fija de solo 2 bytes, el nombre del topic y el payload. La autenticación ocurre una vez, en el CONNECT. A partir de ahí, cada lectura cuesta poco más que su topic y sus datos. MQTT 5 puede reducirlo aún más con los topic aliases, que sustituyen una cadena de topic larga por un entero pequeño.
TLS cambia el panorama para ambos. El handshake es costoso, y los clientes HTTP que abren una nueva conexión TLS por petición lo pagan cada vez. MQTT lo paga una vez por conexión. El keep-alive de HTTP y HTTP/2 reducen la diferencia, pero muchos clientes HTTP con recursos limitados no los usan.
Push frente a sondeo
Si la nube necesita enviar un comando a un dispositivo, HTTP te da tres opciones: sondear con frecuencia y desperdiciar ancho de banda, sondear rara vez y aceptar latencia, o añadir un segundo canal como WebSocket o server-sent events. MQTT simplemente entrega. Un dispositivo suscrito a devices/pump-7/cmd recibe un comando en cuanto se publica, normalmente en lo que tarda el viaje de ida y vuelta por la red.
El sondeo también escala mal en el servidor. Mil dispositivos sondeando cada cinco segundos suponen cientos de peticiones por segundo, haya cambiado algo o no. Con MQTT, el broker está inactivo hasta que hay algo que decir.
Impacto en la batería y en la red
En los dispositivos con batería, la radio suele ser el principal consumo de energía, y lo que importa es con qué frecuencia y durante cuánto tiempo está encendida. El sondeo HTTP despierta la radio según un calendario, abre una conexión, posiblemente negocia TLS, envía cabeceras y espera una respuesta. MQTT mantiene una conexión abierta con pequeños paquetes PINGREQ en cada intervalo de keep alive y, por lo demás, solo transmite datos reales.
Eso no hace que MQTT sea automáticamente mejor para todos los dispositivos con batería. Un sensor que se despierta una vez por hora, envía una lectura y vuelve a dormir no se beneficia de una conexión persistente, y un único POST HTTP puede ser más sencillo. El modelo de conexión persistente compensa cuando los dispositivos envían con frecuencia, necesitan recibir comandos o deben informar de su estado online. En enlaces celulares, donde cada byte y cada establecimiento de conexión cuestan dinero, los paquetes más pequeños y los menos handshakes suman rápidamente.
Ejecuta tu propio benchmark de MQTT vs HTTP
Las cifras dependen de tu red, de la configuración de TLS y de la biblioteca, así que mide. El script siguiente envía 200 lecturas JSON pequeñas por MQTT al servidor MQTT público gratuito y 200 por POST HTTP a un servidor de pruebas local, y luego imprime el tiempo transcurrido en cada caso. Instala antes las dos dependencias.
pip install "paho-mqtt>=2.0" requests
import json
import threading
import time
import uuid
from http.server import BaseHTTPRequestHandler, HTTPServer
import paho.mqtt.client as mqtt
import requests
N = 200
PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:8]}"
reading = json.dumps({"device": "bench-1", "temp": 21.7, "hum": 48})
# --- Endpoint HTTP local mínimo ---
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
self.rfile.read(int(self.headers["Content-Length"]))
self.send_response(204)
self.end_headers()
def log_message(self, *args):
pass
server = HTTPServer(("127.0.0.1", 8080), Handler)
threading.Thread(target=server.serve_forever, daemon=True).start()
# --- HTTP: un POST por lectura, conexión nueva cada vez ---
start = time.perf_counter()
for _ in range(N):
requests.post("http://127.0.0.1:8080/telemetry", data=reading,
headers={"Content-Type": "application/json"})
http_new = time.perf_counter() - start
# --- HTTP: reutiliza una sesión keep-alive ---
session = requests.Session()
start = time.perf_counter()
for _ in range(N):
session.post("http://127.0.0.1:8080/telemetry", data=reading,
headers={"Content-Type": "application/json"})
http_keepalive = time.perf_counter() - start
# --- MQTT: una conexión, QoS 1, espera cada PUBACK ---
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"bench-{uuid.uuid4().hex[:8]}")
client.connect("broker.connectmq.com", 1883, keepalive=30)
client.loop_start()
start = time.perf_counter()
for _ in range(N):
info = client.publish(f"{PREFIX}/telemetry", reading, qos=1)
info.wait_for_publish()
time.sleep(0.11) # mantenerse por debajo de 10 msg/s por cliente del broker público
mqtt_elapsed = time.perf_counter() - start - N * 0.11
client.loop_stop()
client.disconnect()
server.shutdown()
print(f"HTTP new connection : {http_new:.2f}s")
print(f"HTTP keep-alive : {http_keepalive:.2f}s")
print(f"MQTT QoS 1 (net) : {mqtt_elapsed:.2f}s")
Dos advertencias mantienen honesta la comparación. El servidor HTTP se ejecuta en localhost, así que no tiene viaje de ida y vuelta por internet, mientras que el broker MQTT es remoto; apunta la prueba HTTP a un endpoint remoto real si quieres una prueba de latencia equivalente. Además, el broker público limita cada cliente a 10 mensajes por segundo, así que el script espera entre publicaciones y resta ese tiempo. Para contar bytes en lugar de tiempo, ejecuta el mismo script con Wireshark y compara el total de bytes por lectura. Ahí es donde la diferencia suele ser más llamativa.
Cuándo HTTP es la elección correcta
HTTP sigue siendo la mejor herramienta en varias situaciones:
- Envíos poco frecuentes desde dispositivos que duermen durante largos periodos y nunca necesitan comandos.
- Transferencias grandes, como imágenes de firmware, logs o capturas de cámara, donde brillan las peticiones de rango de HTTP, las CDN y la caché.
- APIs públicas y para partners, donde todos los desarrolladores y herramientas ya hablan REST.
- Redes restrictivas que solo permiten HTTPS saliente. Incluso aquí, MQTT sobre WebSocket seguro suele estar permitido, porque empieza como un upgrade HTTPS normal.
Muchos sistemas reales usan ambos: MQTT para telemetría, comandos y estado, y HTTP para el aprovisionamiento, las descargas de firmware y las APIs de back-office. Un pequeño servicio puente que se suscribe a MQTT y expone un endpoint REST es un patrón habitual; la guía de MQTT a API REST con Flask muestra uno.
Cuándo MQTT es la elección correcta
Elige MQTT cuando los dispositivos informan a menudo, cuando la nube debe llegar rápido a los dispositivos, cuando varios consumidores necesitan los mismos datos o cuando necesitas saber qué dispositivos están online. Los mensajes retenidos dan el estado actual a quien se une tarde, el Last Will publica un estado offline cuando un dispositivo se cae y los niveles de QoS te permiten equilibrar sobrecarga y garantías de entrega en cada mensaje. El artículo sobre el modelo publish/subscribe de MQTT explica por qué desacoplar productores y consumidores importa a medida que crece un sistema.
El coste de MQTT es que necesitas un broker, y operarlo de forma fiable es trabajo operativo real, desde los certificados TLS hasta los límites de conexiones. ConnectMQ se encarga de esa parte por ti. Ese es el principal motivo por el que los equipos eligen un broker MQTT gestionado en lugar de mantener el suyo propio. Si todavía estás construyendo los fundamentos, el tutorial de MQTT cubre paso a paso los topics, el QoS y las sesiones.
Lista de decisión
- ¿El servidor necesita enviar datos o comandos a los dispositivos? Si es así, inclínate por MQTT.
- ¿Los dispositivos envían datos más de unas pocas veces por hora? Si es así, inclínate por MQTT.
- ¿Varios servicios consumen los mismos datos? Si es así, inclínate por MQTT.
- ¿El payload es grande o el intercambio es una transferencia de archivo puntual? Si es así, usa HTTP.
- ¿Terceros deben integrarse con herramientas web estándar? Expón HTTP en el borde de tu sistema.
- ¿Es importante el estado online/offline? MQTT te da keep alive y Last Will sin coste adicional.
Prueba MQTT en ConnectMQ
La forma más rápida de decidir entre MQTT y HTTP para tu proyecto es ejecutar tu propio dispositivo contra un broker real. ConnectMQ te da un broker privado y protegido con TLS en los puertos 8883 y 8084, con credenciales generadas, un cliente MQTT en el navegador y un explorador de topics en vivo. Empieza con el plan Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y compara los resultados con tu configuración HTTP actual.
Preguntas frecuentes
¿MQTT es más rápido que HTTP?
Para mensajes pequeños y frecuentes, normalmente sí, porque MQTT reutiliza una conexión y envía cabeceras mucho más pequeñas. Para una única transferencia grande la diferencia es pequeña y las herramientas HTTP suelen ser mejores.
¿MQTT puede sustituir a una API REST?
Puede sustituir los endpoints de dispositivos basados en sondeo, pero REST sigue encajando mejor en APIs públicas, operaciones CRUD y transferencias de archivos. La mayoría de plataformas IoT usan ambos.
¿MQTT consume menos batería que HTTP?
Cuando los dispositivos se comunican a menudo o necesitan recibir comandos, normalmente sí, ya que no hay handshakes repetidos ni sondeo. Los dispositivos que se despiertan rara vez para enviar una lectura pueden notar poco beneficio.
¿Los navegadores pueden usar MQTT igual que usan HTTP?
Sí, mediante MQTT sobre WebSocket. Los clientes de navegador se conectan a una URL como wss://broker.connectmq.com:8084/mqtt usando una biblioteca como MQTT.js.



