Skip to content

WebSockets vs MQTT: Web vs IoT Communication Protocols

Quick Summary

MQTT and WebSockets serve different ecosystems: MQTT excels in IoT environments with its lightweight pub/sub model and Quality of Service guarantees, while WebSockets dominate web-based real-time communication. The two often work together, with MQTT handling device communication and WebSockets bridging to web applications.

At a Glance Comparison

FeatureMQTTWebSockets
Protocol ModelPub/Sub messagingPoint-to-point connection
Target EnvironmentIoT devicesWeb browsers & servers
Message RoutingTopic-basedDirect connection
QoS Levels0, 1, 2 (delivery guarantees)Application-defined
Browser SupportVia WebSocket bridgeNative (99%+)
Message Retention✅ Built-inApplication-defined
Will Messages✅ Last Will and Testament❌ Manual implementation
OverheadMinimal (2-byte header)Low (2-14 byte frames)
Binary Efficiency✅ Optimized✅ Supported
Connection StateSession persistenceStateful during connection
Typical UseSensors, IoT devicesWeb apps, real-time UI

How MQTT Works

MQTT (Message Queuing Telemetry Transport) is a lightweight pub/sub protocol designed for constrained devices:

Core MQTT Concepts

  1. Broker-Centric: All communication goes through a central broker
  2. Topics: Hierarchical message routing (e.g., home/livingroom/temperature)
  3. QoS Levels: Delivery guarantees from fire-and-forget to exactly-once
  4. Retained Messages: Last known good value for new subscribers
  5. Will Messages: Notification if client disconnects unexpectedly

MQTT Client Example

// MQTT in browser via WebSocket transport
const mqtt = require('mqtt');
// Note: MQTT over WebSocket for browser compatibility
const client = mqtt.connect('wss://broker.example.com:8083/mqtt', {
clientId: 'web-client-' + Math.random().toString(16).substr(2, 8),
clean: true,
reconnectPeriod: 1000,
// Last Will and Testament
will: {
topic: 'clients/web-client/status',
payload: 'offline',
qos: 1,
retain: true
}
});
client.on('connect', () => {
console.log('Connected to MQTT broker');
// Publish online status
client.publish('clients/web-client/status', 'online', {
qos: 1,
retain: true
});
// Subscribe to topics
client.subscribe('sensors/+/temperature', { qos: 1 });
client.subscribe('commands/web-client/#', { qos: 2 });
});
client.on('message', (topic, message) => {
console.log(`Topic: ${topic}, Message: ${message.toString()}`);
// Route based on topic
if (topic.startsWith('sensors/')) {
updateSensorDisplay(topic, message);
} else if (topic.startsWith('commands/')) {
handleCommand(topic, message);
}
});
// Publish with QoS
client.publish('control/lights/living-room', JSON.stringify({
state: 'on',
brightness: 80
}), { qos: 1 });

How WebSockets Work

WebSockets provide direct, bidirectional communication between client and server:

// QoS 0: At most once (fire and forget)
client.publish('sensors/data', payload, { qos: 0 });
// Fastest, but message may be lost
// QoS 1: At least once (acknowledged delivery)
client.publish('alerts/warning', payload, { qos: 1 });
// Guaranteed delivery, but may duplicate
// QoS 2: Exactly once (assured delivery)
client.publish('commands/critical', payload, { qos: 2 });
// Slowest, but exactly once delivery guaranteed
// WebSocket - Direct connection
const ws = new WebSocket('wss://api.example.com/socket');
ws.onopen = () => {
console.log('WebSocket connected');
// Send identification
ws.send(JSON.stringify({
type: 'identify',
clientId: 'web-app-user-123'
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
// Handle different message types
switch(data.type) {
case 'sensor-update':
updateSensorDisplay(data);
break;
case 'command':
handleCommand(data);
break;
// Direct message sending
ws.send(JSON.stringify({
type: 'control',
textdevice: 'lightsliving-room',
state: 'on',
brightness: 80
}));

Key Differences

Architecture Model

MQTT: Broker-centric pub/sub

  • Decoupled publishers and subscribers
  • Central message routing
  • Topic-based filtering
  • Many-to-many communication

WebSockets: Point-to-point Structureconnections

  • Direct client-server communication
  • No built-in routing
  • Application-level message handling
  • One-to-one or server-mediated broadcast

MQTT Message Structure

MQTT Fixed Header (2-5 bytes):
┌─────────────────┬─────────────────┐
│ Message Type │ Remaining Length│
│ + Flags (1B) │ (1-4 bytes) │
└─────────────────┴─────────────────┘
Variable Header (optional):
┌─────────────────────────────────────┐
│ Protocol-specific fields (varies) │
└─────────────────────────────────────┘
Payload:
┌─────────────────────────────────────┐
│ Application Data │
└─────────────────────────────────────┘

Quality of Service

WebSocket Frame Structure

WebSocket Frame (2-14 bytes header):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
**MQTT**: Built-in QoS levels
- QoS 0: At most once (fire and forget)
- QoS 1: At least once (acknowledged)
- QoS 2: Exactly once (4-way handshake)
**WebSockets**: OverheadTCPreliabilityonly
- Messages delivered in order
- No built-in acknowledgment
- Application must implement QoS
### Connection Handling
**MQTT**: Session awareness
- Clean/persistent sessions
- Automatic resubscription
- Queued messages for offline clients
- Last Will and Testament
**WebSockets**: Simple connection model
- No built-in session persistence
- Manual reconnection handling
- No offline message queuing
- Application-level presence
## Use Case Analysis
### When MQTT is the Clear Winner
✅ **IoT and embedded devices**:
- Sensor networks
- Smart home devices
- Industrial IoT
- Agricultural monitoring
- Vehicle telemetry
// MQTT excels here due to:
// - Pub/sub reduces connections from 200 to 1 (broker)
// - Built-in QoS handles network interruptions
// - Topic hierarchy organizes data logically
// - Retained messages provide device status
✅ **Constrained environments**:
- Low bandwidth networks
- Battery-powered devices
- Unreliable connections
- High-latency links
✅ **Message patterns**:
- One-to-many broadcasting
- Topic-based routing
- Offline message delivery
- Retained state values
### When WebSockets are Superior
✅ **Web applications**:
- Browser-based real-time apps
- Chat and messaging
- Live dashboards
- Collaborative tools
- Gaming
✅ **Interactive features**:
- Bidirectional communication
- Low-latency requirements
- Request-response patterns
- Direct server push
✅ **Existing web infrastructure**:
- HTTP/HTTPS environments
- Web server integration
- CDN compatibility
- Standard web security
## Bridging MQTT and WebSockets
The two protocols often work together in IoT platforms:
### Common Architecture Pattern
// MQTT for device communication
// WebSockets for web interface
IoTPlatformmqttBrokerMQTTBrokerwsServerWebSocketServer();
// Bridge MQTT to WebSocket
this.bridgeMessages bridgeMessages() {
// Subscribe to all MQTT topics
this.mqttBroker.subscribe('#', (topic, message) => {
// Forward to WebSocket clients interested in this topic
this.wsServer.broadcast({
type: 'mqtt-message',
topic: topic,
payload: message
// Handle WebSocket commands
this.wsServer.on('message', (client, data) => {
if (data.type === 'publish') {
// Publish to MQTT from WebSocket
this.mqttBroker.publish(data.topic, data.payload);
} else if (data.type === 'subscribe') {
// Track WebSocket subscriptions
client.subscriptions.add(data.topic);
}

MQTT over WebSockets

Many MQTT brokers support WebSocket transport, enabling browser access:

// MQTT directly in browser via WebSocket transport
const client = mqtt.connect('wss://broker.example.com:8083/mqtt');
// This is still MQTT protocol, just transported over WebSocket
client.subscribe('sensors/+/data');
client.publish('commands/device', 'restart');

Implementation Examples

Hybrid IoT DeviceDashboard

# IoT device using native MQTT
import paho.mqtt.client as mqtt
import time
import random
const { randomBytes } = require('crypto');
class TemperatureSensor {
constructor(config) {
this.deviceId = config.deviceId || `sensor-${randomBytes(4).toString('hex')}`;
this.location = config.location;
this.reportingInterval = config.reportingInterval || 30000; // 30 seconds
// MQTT configuration
this.client = mqtt.connect(config.brokerUrl, {
clientId: this.deviceId,
client = mqtt.Client("temp-sensor-001")
def publish_sensor_data():
while True:
temperature = 20 + random.uniform(-5, 5)
humidity = 60 + random.uniform(-10, 10)
# Publish sensor data via MQTT
client.publish("sensors/temp-sensor-001/temperature",
f"{temperature:.2f}", qos=1, retain=True)
client.publish("sensors/temp-sensor-001/humidity",
f"{humidity:.2f}", qos=1, retain=True)
time.sleep(10) # Update every 10 seconds
client.connect("mqtt.broker.com", 1883)
client.loop_start()
publish_sensor_data()

Choosing the Right Protocol

Decision Factors

Choose MQTT when:

  • Building IoT device networks
  • Need pub/sub messaging patterns
  • Require QoS guarantees
  • Working with constrained devices
  • Need offline message delivery

Choose WebSockets when:

  • Building web applications
  • Need browser compatibility
  • Require bidirectional communication
  • Working with existing web infrastructure
  • Need simple point-to-point connections

Use both when:

  • Building complete IoT platforms
  • Need device-to-web communication
  • Require different protocols for different parts
  • Want to leverage strengths of each

Working with Protocol Providers

Rather than implementing raw protocols, consider established solutions: MQTT Platforms provide:

  • Managed brokers
  • Device management
  • Security and authentication
  • Scaling and redundancy

WebSocket Services offer:

  • Global infrastructure
  • Automatic scaling
  • Protocol abstraction
  • Multiple transport support

Unified Platforms like Ably provide:

  • Both MQTT and WebSocket support
  • Protocol interoperability
  • Message bridging
  • Unified API across protocols These solutions handle the complexity of protocol management while providing reliable, scalable infrastructure for real-time communication.

Conclusion

The choice between MQTT and WebSockets depends on your application’s domain. These aren’t fundamentally competing protocols but complementary technologies serving different needs. MQTT excels in IoT environments with its pub/sub model and QoS guarantees, while WebSockets provide the ideal solution for web-based real-time communication.

Key Takeaways:

  1. MQTT is designed for IoT, WebSockets for web applications
  2. They often work together in complete solutions
  3. MQTT over WebSockets enables browser access to MQTT
  4. Choose based on your environment and requirements
  5. Consider unified platforms that support both protocols

For most web developers, WebSockets remain the primary choice, with MQTT relevant when extending into IoT device communication.

Further Reading

While raw WebSocket or MQTT implementation requires significant effort, production applications often benefit from using established libraries or services that handle protocol complexities, bridging, and scaling challenges.


Written by Matthew O’Riordan, Co-founder & CEO of Ably, with experience building real-time systems reaching 2 billion+ devices monthly.