Fundamentos

MQTT 5 vs MQTT 3.1.1: qué ha cambiado y si te conviene actualizar

MQTT 5 vs 3.1.1: reason codes, caducidad de sesiones y mensajes, user properties, suscripciones compartidas, topic aliases, petición/respuesta y control de flujo.

Actualizado · 7 min de lectura

MQTT 3.1.1 se convirtió en estándar OASIS en 2014 y más tarde en estándar ISO (ISO/IEC 20922). MQTT 5 llegó como estándar OASIS en 2019. El modelo central —publicación/suscripción sobre topics con tres niveles de QoS— no cambia, pero MQTT 5 añade las funciones para las que la gente no paraba de inventar apaños: informe de errores en condiciones, caducidad, metadatos, suscripciones con balanceo de carga y control de flujo. Esto es lo que cambia de verdad y cuándo importa.

Tabla resumen

FuncionalidadMQTT 3.1.1MQTT 5
Informe de errores6 códigos en CONNACK, solo fallo en SUBACKReason codes en todas las confirmaciones, más reason strings
Desconexión iniciada por el servidorEl socket simplemente se cierraDISCONNECT con un reason code
Duración de la sesiónFlag Clean Session (sí/no)Clean Start + Session Expiry Interval
Caducidad de mensajesNoMessage Expiry Interval
Metadatos personalizadosSolo dentro del payloadUser properties
Suscripciones compartidasExtensiones específicas de cada brokerEstándar $share/group/filter
Topic aliasesNoSí
Petición/respuestaSolo por convenciónResponse Topic + Correlation Data
Control de flujoNoReceive Maximum, Maximum Packet Size
AutenticaciónUsuario/contraseñaAdemás, autenticación mejorada mediante el paquete AUTH

Reason codes en todas partes

En 3.1.1, un CONNECT fallido devuelve uno de seis códigos, y la mayoría de los demás fallos son silenciosos: si una publicación no está autorizada, el broker puede simplemente descartarla o cerrar la conexión. MQTT 5 añade un reason code a CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT y AUTH, opcionalmente con un reason string legible. El broker también puede enviar DISCONNECT para explicar por qué cierra una conexión, como 0x8E Session taken over. La lista completa de códigos habituales está en nuestra guía de errores de conexión MQTT.

Caducidad de sesiones y de mensajes

Session Expiry Interval

MQTT 3.1.1 ofrece un único interruptor: Clean Session. Con cleanSession=false el broker conserva tus suscripciones y mensajes en cola para siempre, lo que puede acumularse con dispositivos que nunca vuelven. MQTT 5 lo divide en Clean Start (¿descartar cualquier sesión existente al conectar?) y Session Expiry Interval (cuántos segundos conservar la sesión tras desconectarse). Ahora un dispositivo puede decir: conserva mi sesión una hora y después límpiala.

Message Expiry Interval

Un publicador puede fijar un tiempo de vida en segundos para cada mensaje. Si no se ha entregado para entonces —por ejemplo, porque el suscriptor estaba offline—, el broker lo descarta. Esto evita que un actuador offline reciba un comando obsoleto horas después, y también se aplica a los mensajes retenidos (retained).

User properties y metadatos de contenido

Los paquetes de MQTT 5 pueden llevar user properties: pares clave/valor UTF-8 arbitrarios, parecidos a las cabeceras HTTP. Úsalas para trace IDs, versiones de esquema o identificadores de origen sin envolver el payload en un sobre. Dos propiedades relacionadas describen el propio payload: Payload Format Indicator (binario o UTF-8) y Content Type (por ejemplo, application/json).

Publicar con propiedades de MQTT 5 (MQTT.js)
client.publish('factory/line-1/temp', JSON.stringify({ c: 21.4 }), {
  qos: 1,
  properties: {
    messageExpiryInterval: 60,
    contentType: 'application/json',
    userProperties: { traceId: 'a1b2c3', schema: 'v2' },
  },
});

Suscripciones compartidas

Normalmente cada suscriptor recibe todos los mensajes que coinciden. Una suscripción compartida reparte en cambio los mensajes entre un grupo, para que puedas escalar un backend horizontalmente. Suscríbete a $share/workers/orders/# desde tres instancias y cada mensaje irá a una sola de ellas. Varios brokers 3.1.1 lo ofrecían como extensión propietaria; MQTT 5 estandariza la sintaxis. Aprende más sobre filtros en topics y comodines en MQTT.

Topic aliases

Los nombres de topic largos se envían con cada publicación. Con los topic aliases, un cliente asocia una vez un topic a un entero pequeño y después solo envía el entero. Cada extremo anuncia cuántos alias acepta mediante Topic Alias Maximum. Esto ahorra ancho de banda a los dispositivos que publican con frecuencia en topics largos sobre enlaces con tarifa por consumo.

Petición/respuesta

MQTT es unidireccional por diseño, pero muchas aplicaciones necesitan respuestas. MQTT 5 añade al paquete de publicación un Response Topic (dónde enviar la respuesta) y Correlation Data (a qué petición corresponde la respuesta). Quien responde lee ambos y publica su respuesta en consecuencia, así que ya no tienes que inventarte tu propio formato de sobre.

Control de flujo y límites

  • Receive Maximum: cuántos mensajes QoS 1 y QoS 2 sin confirmar está dispuesto a gestionar un extremo a la vez. Evita que un broker rápido desborde a un dispositivo lento. Consulta los niveles de QoS de MQTT.
  • Maximum Packet Size: cada extremo puede rechazar paquetes que superen el tamaño que declara.
  • Server Keep Alive: el broker puede sustituir el valor de keep-alive del cliente.
  • Assigned Client Identifier: si te conectas con un client ID vacío, el broker te indica el que ha generado.

Autenticación mejorada

La autenticación de MQTT 3.1.1 se limita a un usuario y una contraseña en el CONNECT (más los certificados de cliente TLS a nivel de transporte). MQTT 5 añade un paquete AUTH y las propiedades Authentication Method y Authentication Data, que permiten esquemas de desafío/respuesta como SCRAM o Kerberos, y la reautenticación en una conexión activa sin desconectarse. El soporte en los brokers varía, así que compruébalo antes de depender de ello.

Novedades menores pero útiles

  • Opciones de suscripción: No Local (no devolverme mis propios mensajes), Retain As Published y Retain Handling.
  • Identificadores de suscripción: indican qué suscripción coincidió con un mensaje entregado.
  • Will Delay Interval: retrasa el Last Will para que una reconexión rápida no lo dispare.

¿Deberías actualizar?

En proyectos nuevos, usa MQTT 5 por defecto: solo la mejora en los errores ya ahorra horas de depuración. Mantén 3.1.1 donde el firmware o las librerías no se puedan actualizar; nada obliga a migrar y ambas versiones conviven en el mismo broker. Cuando actualices, activa la versión en tu cliente (en MQTT.js, protocolVersion: 5) y comprueba que el broker la acepta.

Conéctate con MQTT 5 en el navegador

¿Eres nuevo en el protocolo? Empieza por qué es MQTT, o prueba ahora mismo ambas versiones en el cliente MQTT online.

Preguntas frecuentes

¿MQTT 5 es compatible con MQTT 3.1.1?

No a nivel de protocolo: los formatos de paquete son distintos y el byte de nivel de protocolo es 5 en lugar de 4. En la práctica, la mayoría de los brokers soportan ambas versiones a la vez, así que los clientes MQTT 3.1.1 y MQTT 5 pueden intercambiar mensajes a través del mismo broker.

¿Debo usar MQTT 5 o 3.1.1 en un proyecto nuevo?

Usa MQTT 5 cuando tanto tu broker como tus librerías cliente lo soporten, algo que ocurre con la mayoría de las opciones actuales. Quédate en 3.1.1 para dispositivos limitados o heredados cuyo firmware o librerías solo implementan esa versión.

¿Qué pasó con MQTT 4?

No existe MQTT 4. La versión 3.1.1 usa el nivel de protocolo 4 en el paquete CONNECT, así que la siguiente versión se numeró como 5 para coincidir con su nivel de protocolo y evitar confusiones.