Fundamentos de MQTT

Consumo de ancho de banda de MQTT: cómo calcular la sobrecarga por mensaje

¿Cuántos bytes cuesta realmente un mensaje MQTT? Calcula la sobrecarga de la conexión, el keep alive y la publicación en cada nivel de QoS, añade TCP y TLS y construye una estimación mensual de datos para dispositivos IoT con conexión móvil.

Barra apilada que descompone un mensaje en bytes de payload, MQTT, TCP y TLS para mostrar el consumo de ancho de banda MQTT
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

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:

  1. Handshake TCP: tres segmentos, aproximadamente entre 120 y 180 bytes.
  2. 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.
  3. 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.
  4. 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

  1. Agrupa las muestras en menos mensajes y más grandes cuando la latencia lo permita.
  2. Usa payloads compactos: claves JSON cortas, CBOR o Protobuf. Consulta formato de payload MQTT.
  3. Acorta los topics del dispositivo o usa alias de topic con MQTT 5.
  4. 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.
  5. Mantén las conexiones abiertas y usa sesiones persistentes en lugar de reconectar por cada mensaje.
  6. Ajusta el keep alive al valor más largo que permita el timeout de NAT de tu red.
  7. Publica cuando haya cambios en lugar de a un ritmo fijo cuando los valores sean estables.
  8. 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.

Artículos relacionados

¿Quién inventó MQTT? La historia, de los oleoductos al IoT

MQTT lo inventaron en 1999 Andy Stanford-Clark, de IBM, y Arlen Nipper, de Arcom, para monitorizar oleoductos vía satélite. Sigue su camino hacia el open source, OASIS, ISO y los brokers MQTT gestionados en la nube de hoy.

8 min de lectura

Por qué tu cliente MQTT se desconecta constantemente (y cómo solucionarlo)

Los bucles de reconexión son uno de los problemas más habituales de MQTT. Conoce las cinco causas típicas, desde los client ID duplicados hasta los timeouts de keep alive y los paquetes demasiado grandes, y sigue un flujo de diagnóstico que localiza la tuya.

9 min de lectura

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.