Las propiedades de usuario MQTT (user properties) son pares de cadenas clave/valor que adjuntas a un mensaje MQTT 5, de forma muy parecida a las cabeceras HTTP. Te permiten enviar metadatos como un trace ID, una versión de esquema o la unidad de una medida sin cambiar el formato de payload que tus consumidores ya interpretan. En este artículo aprenderás cómo se comportan las user properties, dónde ayudan de verdad y cómo publicarlas y leerlas en Python, Node.js y la línea de comandos.
Qué son las propiedades de usuario MQTT
MQTT 3.1.1 no tenía sitio para los metadatos. Todo lo que fuera más allá del topic y del payload había que meterlo en el propio payload o codificarlo en el nombre del topic. MQTT 5 introdujo propiedades en la mayoría de los paquetes, y la User Property es la que queda abierta para las aplicaciones.
Datos clave sobre las user properties:
- Cada propiedad es un par de cadenas UTF-8: un nombre y un valor.
- Un mensaje puede llevar cualquier número de ellas, y el mismo nombre puede aparecer más de una vez.
- El orden se conserva. El broker las reenvía en el orden en que se enviaron.
- En los paquetes PUBLISH, el broker las pasa a los suscriptores sin modificarlas.
- Cuentan para el tamaño del paquete y, por tanto, para cualquier límite de tamaño de mensaje.
- También pueden aparecer en CONNECT, SUBSCRIBE, DISCONNECT y otros paquetes, aunque PUBLISH es donde más las usan las aplicaciones.
Como el broker no las interpreta, las user properties son únicamente un contrato entre tus publicadores y tus suscriptores. Son una de las varias funciones de MQTT 5 que hacen el protocolo más amigable para sistemas grandes.
Casos de uso habituales de las propiedades de usuario MQTT
| Caso de uso | Propiedad de ejemplo | Por qué no en el payload |
|---|---|---|
| Trazabilidad distribuida | traceparent=00-4bf9...-01 |
La trazabilidad es transversal; los esquemas de payload no deberían cambiar por ella |
| Versionado de esquemas | schema=telemetry.v3 |
Los consumidores eligen un parser antes de decodificar |
| Metadatos del contenido | unit=celsius, encoding=gzip |
Describe cómo leer el payload |
| Identificación del origen | source=gateway-12, fw=2.4.1 |
Útil para depurar sin tocar los datos |
| Pistas de enrutamiento | tenant=plant-a |
Permite al middleware filtrar sin parsear |
| Marcadores de prueba | synthetic=true |
Permite a los consumidores descartar el tráfico de pruebas |
El hilo común: información sobre el mensaje, no la medida en sí. Si un dashboard necesita un valor para dibujar un gráfico, ese valor va en el payload. Si un valor le dice al software cómo tratar el mensaje, una user property encaja bien.
Para payloads binarios como Protobuf, las user properties resultan especialmente prácticas, porque puedes añadir metadatos sin cambiar el archivo .proto. Consulta los formatos de payload MQTT para esa comparación.
Enviar user properties desde la línea de comandos
Los clientes de Mosquitto admiten user properties cuando seleccionas MQTT 5. Usaremos el servidor MQTT público gratuito en broker.connectmq.com con un prefijo de topic único; es apto para pruebas, no para datos de producción.
Suscríbete primero. El especificador de formato %P imprime las user properties:
mosquitto_sub -V mqttv5 -h broker.connectmq.com -p 1883 -i up-sub-w2c5 \
-t 'connectmq/demo/w2c5/#' -F '%t %p | props: %P'
Luego publica con dos propiedades:
mosquitto_pub -V mqttv5 -h broker.connectmq.com -p 1883 -i up-pub-w2c5 \
-t connectmq/demo/w2c5/line1/temp -m '21.7' \
-D publish user-property unit celsius \
-D publish user-property schema temp.v1
El suscriptor imprime el topic, el payload y unit:celsius schema:temp.v1. Publica el mismo comando con -V mqttv311 y el suscriptor seguirá recibiendo el payload, pero sin propiedades, porque MQTT 3.1.1 no puede transportarlas.
Publicar y leer user properties en Python
En paho-mqtt 2.x, las user properties son una lista de tuplas en un objeto Properties. Una lista y no un diccionario, porque los nombres pueden repetirse:
import time
import uuid
import paho.mqtt.client as mqtt
from paho.mqtt.properties import Properties
from paho.mqtt.packettypes import PacketTypes
BROKER = "broker.connectmq.com"
TOPIC = "connectmq/demo/w2c5/line1/pressure"
def on_connect(client, userdata, flags, reason_code, properties):
client.subscribe(TOPIC, qos=1)
def on_subscribe(client, userdata, mid, reason_code_list, properties):
props = Properties(PacketTypes.PUBLISH)
props.UserProperty = [
("trace-id", uuid.uuid4().hex),
("unit", "bar"),
("source", "gateway-12"),
]
client.publish(TOPIC, "2.31", qos=1, properties=props)
def on_message(client, userdata, msg):
user_props = dict(getattr(msg.properties, "UserProperty", []))
print(msg.topic, msg.payload.decode(), user_props)
client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
client_id=f"up-py-{uuid.uuid4().hex[:8]}",
protocol=mqtt.MQTTv5,
)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message
client.connect(BROKER, 1883, keepalive=30)
client.loop_start()
time.sleep(3)
client.loop_stop()
client.disconnect()
Convertirlas en un diccionario es cómodo, pero solo si sabes que tus nombres son únicos. Si permites nombres repetidos, conserva la lista.
User properties en Node.js
MQTT.js v5 expone las user properties como un objeto simple en properties.userProperties. Un valor puede ser una cadena o un array de cadenas en el caso de nombres repetidos:
const mqtt = require("mqtt");
const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
clientId: "up-js-" + Math.random().toString(16).slice(2, 10),
protocolVersion: 5,
});
const topic = "connectmq/demo/w2c5/line1/flow";
client.on("connect", () => {
client.subscribe(topic, { qos: 1 }, () => {
client.publish(topic, "12.4", {
qos: 1,
properties: {
userProperties: { unit: "m3/h", tag: ["calibrated", "line1"] },
},
});
});
});
client.on("message", (t, payload, packet) => {
console.log(t, payload.toString(), packet.properties?.userProperties);
client.end();
});
User properties frente a niveles de topic y campos del payload
Hay tres lugares donde poner un dato en un mensaje MQTT, y cada uno tiene un coste distinto:
| Ubicación | Adecuada para | Visible para | Coste |
|---|---|---|---|
| Nivel del topic | Enrutamiento y filtrado de suscripciones (instalación, línea, dispositivo) | El broker, todos los suscriptores, los comodines | Forma parte de cada cadena de topic; cambiarla rompe suscripciones |
| User property | Instrucciones de tratamiento, trazabilidad, versión de esquema | Solo los suscriptores; el broker la ignora | Bytes en cada mensaje; se pierde en saltos MQTT 3.1.1 |
| Campo del payload | Datos de negocio que los consumidores almacenan o muestran | Los suscriptores tras decodificar | Añadirlo requiere cambiar el esquema |
Una regla práctica útil: si un suscriptor necesita filtrar por ello, usa el topic. Si un suscriptor necesita decidir cómo procesar el mensaje antes de decodificarlo, usa una user property. Si el suscriptor lo almacena o lo muestra, ponlo en el payload.
Por ejemplo, un valor unit podría ir tanto en una propiedad como en el payload. Si todos los consumidores guardan la unidad junto al valor, ponla en el payload para que sobreviva al escribirse en una base de datos. Si la unidad es fija por topic y solo la comprueba una capa de validación, una propiedad es más limpia. Ten en cuenta que las suscripciones con comodines solo filtran por niveles de topic: un suscriptor no puede pedir al broker "mensajes en los que tenant sea plant-a" basándose en una user property.
Pautas de diseño
- Define un vocabulario reducido. Poneos de acuerdo entre equipos en un puñado de nombres y documentadlos. Las propiedades improvisadas se convierten rápidamente en ruido.
- Mantenlas cortas. Las propiedades viajan con cada mensaje. Diez cabeceras largas en una lectura de sensor de 20 bytes pueden multiplicar su tamaño.
- No pongas secretos en ellas. Son tan visibles como el payload para cualquiera que pueda suscribirse.
- No dependas de ellas para datos críticos si algunos consumidores siguen usando MQTT 3.1.1. Esos consumidores las perderán sin avisar.
- Usa formatos estándar cuando existan, como
traceparentde W3C para la trazabilidad, para que las herramientas puedan entenderlas. - Prefiere content type para el tipo de payload. MQTT 5 tiene una propiedad Content Type dedicada y un Payload Format Indicator; úsalos en lugar de una user property
content-typepersonalizada.
Resolución de problemas con las user properties
Faltan las propiedades en el suscriptor. El suscriptor o el publicador se conectó con MQTT 3.1.1. Ambas conexiones deben ser MQTT 5.
Los mensajes se rechazan por ser demasiado grandes. Las propiedades cuentan para el tamaño del paquete. En un plan o broker con límite de tamaño, recórtalas. Nuestro artículo sobre el límite de tamaño de mensaje en MQTT explica cómo se aplica el límite.
Los valores aparecen como arrays inesperadamente. En MQTT.js, un nombre repetido se convierte en un array. Gestiona ambas formas o evita repetir nombres.
Los mensajes reenviados o republicados pierden las propiedades. Cualquier componente que lea y vuelva a publicar un mensaje debe copiar las propiedades explícitamente; muchos scripts sencillos no lo hacen.
User properties en ConnectMQ
ConnectMQ reenvía sin cambios las user properties de MQTT 5 entre publicadores y suscriptores, como cualquier broker conforme al estándar. Recuerda que cuentan para el tamaño del mensaje: 256 KB en el plan Serverless (Free), 1 MB en el plan Serverless (Paid) y 64 KB en el servidor MQTT público gratuito. Para ver tus metadatos en la práctica, suscríbete con el comando de Mosquitto anterior o con tu propio cliente contra tu broker, usando las credenciales del portal. Si todavía estás eligiendo infraestructura, nuestra visión general de un broker MQTT gestionado explica lo que obtienes, y el tutorial de MQTT cubre los fundamentos.
Empieza con ConnectMQ
Regístrate en app.connectmq.com y crea un broker en el plan Serverless gratuito, sin tarjeta de crédito. Conéctate con MQTT 5, añade un trace ID a tus mensajes y síguelos desde el dispositivo hasta el dashboard en tu propio broker MQTT en la nube.
Preguntas frecuentes
¿Pueden repetirse los nombres de las user properties?
Sí. MQTT 5 permite el mismo nombre más de una vez y el broker conserva el orden. Guárdalas como lista si dependes de ello.
¿Modifica el broker las user properties?
En los paquetes PUBLISH, el broker las reenvía sin cambios a los suscriptores. No las interpreta ni las filtra.
¿Están disponibles las user properties en MQTT 3.1.1?
No. Son una función de MQTT 5. Un suscriptor 3.1.1 recibe el payload sin ninguna propiedad.
¿Cuentan las user properties para el tamaño del mensaje?
Sí. Forman parte del paquete, así que cuentan para el tamaño máximo de paquete del broker.



