El consumo de ancho de banda de MQTT es fácil de estimar una vez que sabes de dónde sale cada byte: el propio paquete MQTT, las cabeceras TCP/IP que lo transportan, el cifrado TLS que lo envuelve y el tráfico de fondo de las conexiones y los keep alive. Esta guía calcula cada capa para un mensaje de telemetría realista con QoS 0, 1 y 2, y después convierte las cifras en una estimación mensual de datos que puedes usar al elegir una tarifa móvil para tus dispositivos.
Por qué MQTT es ligero y adónde siguen yendo los bytes
La cabecera fija de MQTT ocupa apenas dos bytes, no hay cabeceras de texto como en HTTP y una única conexión de larga duración sustituye a un handshake por petición. Eso hace que la sobrecarga del protocolo por mensaje sea mínima. Pero en un enlace medido pagas por bytes IP, no por bytes MQTT, y con payloads pequeños dominan las capas inferiores. Un modelo mental útil tiene cuatro capas:
| Capa | Coste por mensaje | Notas |
|---|---|---|
| Payload | Tus datos | A menudo entre 20 y 200 bytes de JSON en telemetría |
| MQTT | De 2 a 6 bytes + nombre del topic | La longitud del topic suele ser el mayor coste de MQTT |
| TLS | Entre 22 y 29 bytes por registro, aproximadamente | Depende de la versión de TLS y del cifrado |
| TCP/IP | 40 bytes por segmento (IPv4, sin opciones) | A menudo 52 con marcas de tiempo TCP; 60 con IPv6 |
A esto se suman dos costes de fondo que no son por mensaje: el establecimiento de la conexión (TCP, handshake TLS, CONNECT) y los pings de keep alive durante la inactividad. Ambos se tratan más abajo. Para la estructura a nivel de byte de la capa MQTT, consulta la guía de estructura de los paquetes MQTT.
Sobrecarga de MQTT por mensaje según el QoS
Tomemos un ejemplo típico: MQTT 3.1.1, el topic plant1/line2/pump3/telemetry (28 caracteres) y un payload JSON de 48 bytes como {"t":1760601600,"flow":12.4,"p":3.1,"temp":41.7}.
El paquete PUBLISH con QoS 0 es:
- Cabecera fija: 2 bytes (tipo y flags, un byte de longitud restante)
- Topic: prefijo de longitud de 2 bytes + 28 bytes = 30 bytes
- Payload: 48 bytes
- Total: 80 bytes
Con QoS 1 y 2, el PUBLISH incorpora un identificador de paquete de 2 bytes y se añaden paquetes de acuse de recibo de 4 bytes cada uno:
| QoS | Paquetes en la red | Bytes MQTT | Sobrecarga frente al payload |
|---|---|---|---|
| 0 | PUBLISH (80) | 80 | 32 bytes |
| 1 | PUBLISH (82) + PUBACK (4) | 86 | 38 bytes |
| 2 | PUBLISH (82) + PUBREC + PUBREL + PUBCOMP (4 cada uno) | 94 | 46 bytes |
Con MQTT 5, suma un byte por la longitud de propiedades vacía en el PUBLISH; los acuses de recibo de éxito sin propiedades se mantienen en 4 bytes. Así pues, en la capa MQTT, la elección del QoS solo cambia el coste de forma moderada. La diferencia real aparece en la capa de transporte, porque cada paquete adicional suele suponer un segmento TCP adicional. La guía de niveles de QoS de MQTT explica cuándo compensan las garantías de entrega adicionales.
El nombre del topic suele ser el mayor coste de MQTT
En el ejemplo anterior, el topic supone 30 de los 32 bytes de sobrecarga de QoS 0. Los topics profundos de estilo ISA-95 pueden superar fácilmente los 50 caracteres. Dos remedios: mantener concisos los topics del lado del dispositivo o usar los alias de topic de MQTT 5, que sustituyen el topic por un número de 2 bytes tras la primera publicación. La guía del alias de topic MQTT muestra el ahorro en detalle.
Añadir TCP/IP y TLS
Cada paquete MQTT enviado por separado viaja en un segmento TCP con al menos 40 bytes de cabeceras IPv4 y TCP. El receptor confirma los datos con ACK de TCP, que también son segmentos de 40 bytes salvo que puedan ir a caballo de datos que circulen en sentido contrario. El comportamiento del ACK retardado varía según el sistema operativo y la pila de red, así que considera aproximados los costes de los ACK.
TLS envuelve cada escritura en un registro. Con TLS 1.3 y un cifrado AES-GCM, cada registro añade 5 bytes de cabecera, 1 byte de tipo de contenido interno y una etiqueta de autenticación de 16 bytes: 22 bytes. TLS 1.2 con AES-GCM añade 29 bytes, por un nonce explícito de 8 bytes.
Juntándolo todo para un mensaje de telemetría, con IPv4 sin opciones TCP, TLS 1.3 y contando un ACK TCP puro por cada segmento de datos:
| QoS | TCP sin cifrar (puerto 1883) | TLS 1.3 (puerto 8883) |
|---|---|---|
| 0 | 80 + 40 + 40 ACK = 160 bytes | 102 + 40 + 40 ACK = 182 bytes |
| 1 | 122 + 44 + 40 ACK = 206 bytes | 144 + 66 + 40 ACK = 250 bytes |
| 2 | 122 + 3 x 44 + 2 ACK, unos 335 bytes | 144 + 3 x 66 + 2 ACK, unos 420 bytes |
Para un payload de 48 bytes, el coste en la red es aproximadamente de cuatro a ocho veces el de los datos. Esa proporción disminuye a medida que crecen los payloads: un payload de 1 KB tiene casi la misma sobrecarga absoluta, que pasa a ser una fracción pequeña. Por eso agrupar lecturas, por ejemplo un mensaje con diez muestras en lugar de diez mensajes, es la optimización de ancho de banda más eficaz.
TLS no es opcional en despliegues reales y, como muestra la tabla, su coste por mensaje es moderado. Su mayor coste es el handshake.
Costes de establecimiento de la conexión
Cada nueva conexión paga por:
- Handshake TCP: tres segmentos, aproximadamente entre 120 y 180 bytes.
- Handshake TLS: normalmente unos pocos kilobytes, sobre todo la cadena de certificados del servidor. La reanudación de sesión de TLS 1.3, si tu librería la admite, lo reduce considerablemente.
- CONNECT y CONNACK: un CONNECT con un client ID de 20 caracteres, usuario y contraseña ronda los 80 bytes; CONNACK ocupa 4 bytes en MQTT 3.1.1.
- SUBSCRIBE y SUBACK por cada suscripción, si no usas una sesión persistente.
Así, una reconexión puede costar tanto como decenas de mensajes de telemetría. Los dispositivos que se conectan, publican una vez y se desconectan cada minuto desperdician la mayor parte de sus datos en handshakes. Salvo que el dispositivo duerma durante periodos largos, mantén la conexión abierta y usa una sesión persistente para no tener que volver a suscribirte tras cada reconexión. La guía de sesiones persistentes explica cómo.
Costes del keep alive
Cuando un cliente no tiene nada que enviar durante el intervalo de keep alive, envía PINGREQ (2 bytes) y el broker responde con PINGRESP (2 bytes). Con TLS 1.3 y TCP/IP, un intercambio de ping supone unos 64 + 64 bytes, más un ACK: aproximadamente 170 bytes.
| Keep alive | Pings al día en inactividad | Datos aproximados al día |
|---|---|---|
| 30 s | 2.880 | unos 485 KB |
| 60 s | 1.440 | unos 240 KB |
| 300 s | 288 | unos 48 KB |
| 900 s | 96 | unos 16 KB |
Los pings solo se envían cuando la conexión está inactiva, así que un dispositivo que publica cada 30 segundos con un keep alive de 60 segundos no envía ningún ping. Los intervalos más largos ahorran datos, pero se arriesgan a los timeouts de NAT de las redes móviles, que cortan las conexiones inactivas y obligan a una reconexión costosa. Ajústalo siguiendo las indicaciones del artículo sobre el intervalo de keep alive de MQTT.
Estimar los datos mensuales de un dispositivo móvil
Esta calculadora en Python combina todas las piezas. Ajusta los parámetros a tu dispositivo:
def mqtt_monthly_bytes(
payload=48, topic_len=28, qos=1, msgs_per_day=1440,
tls=True, reconnects_per_day=2, handshake_bytes=5000,
keepalive_s=120, idle_seconds_per_day=0,
):
ip_tcp = 40
tls_rec = 22 if tls else 0
publish = 2 + 2 + topic_len + payload + (2 if qos else 0)
def seg(mqtt_bytes):
return mqtt_bytes + tls_rec + ip_tcp
if qos == 0:
per_msg = seg(publish) + ip_tcp
elif qos == 1:
per_msg = seg(publish) + seg(4) + ip_tcp
else:
per_msg = seg(publish) + 3 * seg(4) + 2 * ip_tcp
pings = idle_seconds_per_day / keepalive_s if keepalive_s else 0
ping_bytes = pings * (2 * seg(2) + ip_tcp)
connect_bytes = reconnects_per_day * (handshake_bytes if tls else 300)
per_day = msgs_per_day * per_msg + ping_bytes + connect_bytes
return per_day * 30
for qos in (0, 1, 2):
mb = mqtt_monthly_bytes(qos=qos) / 1_000_000
print(f"QoS {qos}: {mb:.1f} MB per month")
Con un mensaje por minuto con QoS 1 sobre TLS, el resultado ronda los 11 MB al mes por dispositivo, de los que solo una pequeña parte procede de las dos reconexiones supuestas. Cambia msgs_per_day a 144 (cada diez minutos) con un keep alive de 300 segundos y añadiendo el tiempo de inactividad, y el total cae drásticamente. Son estimaciones calculadas, no mediciones; valídalas comprobando el consumo real en una SIM de prueba o capturando el tráfico durante un día con tcpdump y sumando los bytes.
Lista para reducir el ancho de banda
- Agrupa las muestras en menos mensajes y más grandes cuando la latencia lo permita.
- Usa payloads compactos: claves JSON cortas, CBOR o Protobuf. Consulta formato de payload MQTT.
- Acorta los topics del dispositivo o usa alias de topic con MQTT 5.
- Elige el QoS por topic: QoS 0 para telemetría frecuente en la que una pérdida ocasional es aceptable, QoS 1 para eventos y comandos.
- Mantén las conexiones abiertas y usa sesiones persistentes en lugar de reconectar por cada mensaje.
- Ajusta el keep alive al valor más largo que permita el timeout de NAT de tu red.
- Publica cuando haya cambios en lugar de a un ritmo fijo cuando los valores sean estables.
- Evita suscripciones innecesarias: una suscripción con comodín en un dispositivo recibe todos los mensajes coincidentes, lo que consume datos de bajada.
Ejecuta dispositivos eficientes en ConnectMQ
ConnectMQ admite MQTT 3.1.1 y 5.0, incluidos los alias de topic y la expiración de sesión, sobre TLS en el puerto 8883 con un certificado de Let's Encrypt, así que las optimizaciones anteriores funcionan sin configuración especial. Crea prototipos en el broker MQTT público gratuito y después mide el tráfico real contra un broker privado. El tutorial de MQTT cubre los fundamentos si el protocolo es nuevo para ti.
Empieza con ConnectMQ
Un broker MQTT gestionado te permite centrarte en la eficiencia de los dispositivos en lugar de en la operación de servidores. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y usa el explorador de topics en directo para ver exactamente qué envían tus dispositivos. Para una comparativa más amplia, lee nuestra guía para elegir un broker MQTT en la nube.
Preguntas frecuentes
¿Cuánta sobrecarga añade MQTT por mensaje?
En la capa MQTT, un PUBLISH añade 4 bytes más el nombre del topic con QoS 0, y 6 bytes más el topic con QoS 1 y 2, antes de los acuses de recibo. TCP/IP y TLS añaden encima unos 60 bytes o más por paquete.
¿Encarece mucho TLS el uso de MQTT?
Por mensaje, TLS 1.3 añade unos 22 bytes por registro, algo moderado. El coste mayor es el handshake, de unos pocos kilobytes por cada nueva conexión, así que mantén las conexiones abiertas en lugar de reconectar con frecuencia.
¿Cuántos datos consume el keep alive de MQTT?
Un intercambio de ping cuesta unos pocos bytes en la capa MQTT, pero alrededor de 170 bytes con TCP, IP y TLS. Con un intervalo de 60 segundos en una conexión inactiva, son aproximadamente 240 KB al día.
¿Es QoS 0 siempre lo más barato?
Sí, en bytes, porque no envía paquetes de acuse de recibo. Pero si los mensajes perdidos obligan a tu aplicación a reenviar datos o a hacer sondeos, QoS 1 puede acabar siendo más barato en conjunto.



