MQTT vs WebSocket suena a elegir entre dos protocolos rivales, pero en realidad es una cuestión de capas. WebSocket es un transporte que da al navegador un canal full-duplex hacia un servidor; MQTT es un protocolo de mensajería que define topics, suscripciones, garantías de entrega y estado de sesión, y puede funcionar sobre ese canal. Esta guía explica la diferencia, muestra lo que una app con WebSocket puro tiene que construir a mano y recorre paso a paso cómo conectar un navegador a un broker MQTT mediante WebSocket seguro.
Qué es realmente WebSocket
WebSocket (RFC 6455) empieza como una petición HTTP con la cabecera Upgrade: websocket. Cuando el servidor acepta, la conexión cambia a un formato de tramas ligero en el que cualquiera de los dos lados puede enviar mensajes de texto o binarios en cualquier momento. Resuelve un problema concreto: antes de que existiera, los navegadores no podían mantener una conexión abierta y bidireccional con un servidor.
Igual de importante es lo que WebSocket no define. No hay topics, ni suscripciones, ni confirmaciones más allá de TCP, ni noción de quién debe recibir un mensaje, ni comportamiento de reconexión, ni estado que sobreviva a una conexión caída. Cada aplicación construida sobre un WebSocket puro inventa su propio formato de mensaje y su propia semántica.
Qué aporta MQTT
MQTT es un protocolo de aplicación con un conjunto de paquetes bien definido: CONNECT, PUBLISH, SUBSCRIBE, confirmaciones, etc. Te ofrece:
- Enrutamiento por topics a través de un broker, con comodines
+y#. - Garantías de entrega QoS 0, 1 y 2 por mensaje.
- Retained messages para que un cliente nuevo reciba de inmediato el último valor conocido.
- Sesiones persistentes que encolan mensajes mientras un cliente está desconectado.
- Keep alive y Last Will para detectar si un cliente está en línea o no.
- Extras de MQTT 5 como la expiración de mensajes, los response topics para petición/respuesta, las propiedades de usuario y los reason codes.
MQTT normalmente funciona sobre TCP o TLS, pero la especificación también define cómo transportarlo sobre WebSocket mediante el subprotocolo mqtt. Eso es lo que permite que un navegador hable el mismo protocolo que un ESP32. Para entender cómo enruta el broker todo esto, consulta cómo funciona MQTT.
Tabla comparativa MQTT vs WebSocket
| Aspecto | WebSocket puro | MQTT (sobre TCP o WebSocket) |
|---|---|---|
| Capa | Transporte (con tramas, full-duplex) | Protocolo de mensajería de aplicación |
| Formato de mensaje | El que tú definas | Paquetes estándar con topics y propiedades |
| Enrutamiento | Lo decide el código de tu servidor | El broker enruta por topic y comodín |
| Difusión a muchos clientes | Rastreas conexiones y recorres un bucle | El broker entrega a todos los suscriptores coincidentes |
| Garantías de entrega | Ninguna más allá de TCP | QoS 0, 1, 2 |
| Último estado conocido | Construyes una caché | Retained messages |
| Búfer sin conexión | Lo construyes tú | Sesiones persistentes |
| Presencia | Construyes heartbeats | Keep alive y Last Will |
| Soporte de dispositivos | Sobre todo navegadores y servidores | Microcontroladores, gateways, servidores, navegadores |
| Interoperabilidad | Solo con tu propio servidor | Cualquier cliente y broker MQTT |
Lo que tiene que construir una app con WebSocket puro
Este es un retrato realista del backend de un dashboard con WebSocket puro. El servidor mantiene un mapa de navegadores conectados. Los dispositivos envían lecturas por HTTP o por su propio socket. Cuando llega una lectura, el servidor decide quién debe recibirla, recorre los sockets correspondientes y envía JSON. Y entonces llegan los requisitos:
- Los navegadores solo deben recibir datos de las instalaciones que están viendo, así que añades un tipo de mensaje "subscribe" y un esquema de filtrado.
- Un dashboard recién abierto debe mostrar los valores actuales al instante, así que añades una caché de últimos valores.
- Los clientes móviles se desconectan a menudo, así que añades heartbeats y lógica de reconexión en el navegador.
- Los comandos necesitan confirmación, así que añades IDs de mensaje y acuses de recibo.
- Necesitas un segundo servidor por carga, así que añades una capa pub/sub entre servidores para que una lectura recibida en uno llegue a los navegadores conectados al otro.
Llegados a ese punto, has reconstruido un broker, pero sin la interoperabilidad. Con MQTT sobre WebSocket, todas esas funciones ya existen y dispositivos y navegadores comparten un único sistema.
WebSocket puro sigue siendo la opción adecuada para algunos casos: un chat dentro de una app web existente, la edición colaborativa, un servidor de juegos o cualquier caso en el que ambos extremos sean tu propio código y la semántica de los mensajes sea exclusiva de tu aplicación.
Conecta un navegador a MQTT sobre WebSocket
ConnectMQ expone MQTT sobre WebSocket en el puerto 8083 y sobre WebSocket seguro en el puerto 8084, ambos en la ruta /mqtt. Los navegadores que cargan páginas por HTTPS deben usar la variante segura. El ejemplo siguiente usa MQTT.js desde una CDN y el servidor MQTT público gratuito, así que puedes guardarlo como archivo HTML y abrirlo directamente.
// Carga primero MQTT.js, por ejemplo:
// <script src="https://unpkg.com/mqtt@5.10.1/dist/mqtt.min.js"></script>
const prefix = "connectmq/demo/" + Math.random().toString(16).slice(2, 10);
const clientId = "browser-" + Math.random().toString(16).slice(2, 10);
const client = mqtt.connect("wss://broker.connectmq.com:8084/mqtt", {
clientId,
protocolVersion: 5,
clean: true,
keepalive: 30,
reconnectPeriod: 2000,
});
client.on("connect", () => {
console.log("connected as", clientId);
client.subscribe(prefix + "/sensors/+/temperature", { qos: 1 });
// Publica una lectura retenida para que quien se conecte después la vea al instante
client.publish(
prefix + "/sensors/room1/temperature",
JSON.stringify({ value: 22.3, ts: Date.now() }),
{ qos: 1, retain: true }
);
});
client.on("message", (topic, payload, packet) => {
console.log(topic, payload.toString(), "retain:", packet.retain);
});
client.on("reconnect", () => console.log("reconnecting..."));
client.on("error", (err) => console.error("mqtt error:", err.message));
console.log("Publish test data with:");
console.log(`mosquitto_pub -h broker.connectmq.com -p 1883 -i cli-${clientId} -t "${prefix}/sensors/room2/temperature" -m '{"value":19.8}'`);
Ejecuta en una terminal el comando mosquitto_pub que se imprime y la consola del navegador mostrará el mensaje llegando desde un cliente TCP normal. Esa es la gracia de MQTT sobre WebSocket: el transporte cambia, pero los topics y la semántica son los mismos.
Para un broker privado, sustituye el host de la URL por la dirección de tu broker y añade username: "YOUR_USERNAME" y password: "YOUR_PASSWORD" a las opciones, junto con clientId: "YOUR_CLIENT_ID". Recuerda que todo lo que se envía a un navegador es visible para su usuario, así que da a los clientes de navegador sus propias credenciales limitadas en lugar de reutilizar las de dispositivos o del backend. La guía de MQTT sobre WebSocket trata en más profundidad los puertos, los proxies y la resolución de problemas, y MQTT en el navegador con JavaScript construye un dashboard completo.
Rendimiento y sobrecarga
MQTT sobre WebSocket añade una pequeña cabecera de trama WebSocket a cada paquete MQTT, además del upgrade HTTP inicial. Para el tráfico de un dashboard ese coste es despreciable. Para dispositivos con recursos limitados no hay ningún motivo para usar WebSocket; conéctate por TCP en el 1883 o por TLS en el 8883 y ahorra bytes. Un reparto habitual es tener los dispositivos en el 8883 y los navegadores en el 8084, hablando ambos con el mismo broker.
Errores comunes
- Ruta incorrecta. Muchos brokers, incluido ConnectMQ, esperan
/mqtt. Conectarse a la ruta raíz falla con un error de handshake. - Contenido mixto. Una página servida por HTTPS no puede abrir una conexión
ws://. Usawss://y el puerto 8084. - Client IDs compartidos. Dos pestañas del navegador con el mismo client ID fijo en el código se expulsarán una a otra repetidamente. Genera uno por pestaña.
- Proxies corporativos. Algunos proxies interfieren con los upgrades a WebSocket en puertos no estándar. Haz pruebas desde las redes que usan realmente tus usuarios.
- Fuga de secretos. Nunca incrustes credenciales del backend o de dispositivos en el código del frontend.
¿Cuál deberías elegir?
Si estás construyendo una función en tiempo real en la que ambos extremos son tu propio código web y la semántica es exclusiva, WebSocket puro está bien. Si los navegadores necesitan ver datos de dispositivos, si varios clientes comparten los mismos datos o si necesitas garantías, estado retenido y presencia, elige MQTT y usa WebSocket como su transporte en el navegador. Un broker MQTT gestionado te da ambos endpoints, TCP para dispositivos y WSS para navegadores, sin que tengas que operar la infraestructura. Para una introducción completa al protocolo, empieza por el tutorial de MQTT.
Crea dashboards en tiempo real con ConnectMQ
ConnectMQ sirve MQTT en los puertos 1883 y 8883 y MQTT sobre WebSocket en el 8083 y el 8084 con un certificado de Let's Encrypt, de modo que dispositivos y navegadores se conectan al mismo broker. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y pruébalo con el cliente MQTT integrado en el navegador del portal antes de escribir una sola línea de código frontend.
Preguntas frecuentes
¿Es MQTT mejor que WebSocket?
No son alternativas de la misma capa. WebSocket es un transporte; MQTT es un protocolo de mensajería que puede funcionar sobre WebSocket. Usa MQTT cuando necesites topics, difusión a muchos clientes y garantías de entrega.
¿Puede un navegador conectarse directamente a un broker MQTT?
Sí, si el broker admite MQTT sobre WebSocket. Con ConnectMQ, usa wss://broker.connectmq.com:8084/mqtt y una librería como MQTT.js.
¿Por qué falla mi conexión MQTT por WebSocket en una página HTTPS?
Los navegadores bloquean las conexiones ws:// inseguras desde páginas HTTPS. Cambia a wss:// en el puerto 8084 y comprueba que la ruta sea /mqtt.
¿Deberían los dispositivos IoT usar MQTT sobre WebSocket?
Normalmente no. Los dispositivos deberían usar MQTT directamente sobre TCP o TLS, que tiene menos sobrecarga. WebSocket es sobre todo para navegadores y para redes que solo permiten tráfico web.



