·12 min read·BASHCAT 技術團隊·embedded

MQTT vs HTTP: How to Choose the Right IoT Communication Protocol?

An in-depth comparison of MQTT and HTTP for IoT applications, covering bandwidth, latency, power consumption, and implementation complexity to help you choose the most suitable communication protocol.

#MQTT#HTTP#Internet of Things#IoT#Communication Protocol#ESP32#Embedded Systems

MQTT vs HTTP: How to Choose the Right IoT Communication Protocol?

IoT devices need to communicate with the cloud, and choosing the right communication protocol directly impacts system performance, battery life, and maintenance costs. This article provides an in-depth comparison of MQTT and HTTP, the two mainstream protocols, to help you make the best choice.

Protocol Overview

HTTP (HyperText Transfer Protocol)

HTTP is the foundational protocol of the Web, using a request-response model:

Client ──Request──> Server
Client <──Response── Server

Characteristics:

  • Stateless protocol
  • Request-response model
  • Text-based headers (HTTP/1.1)
  • Broad support and mature toolchain

MQTT (Message Queuing Telemetry Transport)

MQTT is a lightweight publish-subscribe protocol designed specifically for IoT:

Publisher ──Publish Message──> Broker ──Push──> Subscriber

Characteristics:

  • Publish/Subscribe model
  • Minimal packet overhead
  • Persistent connections
  • QoS (Quality of Service) guarantees

Performance Comparison

Bandwidth Consumption

Item MQTT HTTP
Header Size 2-5 bytes 700+ bytes
Connection Establishment Once Per request
Keep-alive Minimal N/A

For scenarios involving frequent transmission of small data packets, MQTT's bandwidth advantage is significant:

// MQTT sending sensor data (ESP32)
void send_mqtt_data(float temperature, float humidity) {
    char payload[64];
    snprintf(payload, sizeof(payload),
             "{\"temp\":%.1f,\"hum\":%.1f}", temperature, humidity);

    // Actual transmission: 2 bytes fixed header + topic length + payload
    // Total approximately 30-50 bytes
    mqtt_client_publish(client, "sensors/living-room", payload, 0, 0);
}

// HTTP sending the same data
void send_http_data(float temperature, float humidity) {
    char body[64];
    snprintf(body, sizeof(body),
             "{\"temp\":%.1f,\"hum\":%.1f}", temperature, humidity);

    // HTTP request includes:
    // - Request line: POST /api/sensors HTTP/1.1
    // - Host, Content-Type, Content-Length and other headers
    // - Empty line + body
    // Total approximately 300-500 bytes
    http_client_post(client, "/api/sensors", body);
}

Latency Comparison

MQTT's persistent connections significantly reduce latency:

Scenario MQTT HTTP
Initial Connection ~100ms ~100ms
Subsequent Messages ~10ms ~100ms
Server Push Real-time Requires polling

Power Consumption

For battery-powered devices, MQTT is more power-efficient:

HTTP per-request flow:
1. TCP handshake (3 round trips)
2. TLS handshake (2-4 round trips)
3. HTTP request/response
4. Connection close

MQTT persistent connection:
1. Initial connection establishment (same as HTTP)
2. Subsequent messages only require small packets
3. Keep-alive maintains the connection

Measured data (ESP32 + WiFi):

Operation MQTT HTTP
Send one data point 15 mAs 80 mAs
Send once per minute 900 mAs/hr 4800 mAs/hr

Feature Comparison

Quality of Service (QoS)

MQTT provides three QoS levels:

// QoS 0: At most once (Fire and Forget)
// No delivery guarantee, lowest overhead
mqtt_publish(client, topic, payload, QOS_0, false);

// QoS 1: At least once
// Guaranteed delivery, may duplicate
mqtt_publish(client, topic, payload, QOS_1, false);

// QoS 2: Exactly once
// Guaranteed delivery without duplicates, highest overhead
mqtt_publish(client, topic, payload, QOS_2, false);

HTTP requires implementing retry mechanisms at the application layer.

Server Push

MQTT natively supports server push:

// Subscribe to a topic, automatically receive new messages
void mqtt_message_handler(char *topic, char *payload) {
    if (strcmp(topic, "commands/device-001") == 0) {
        handle_command(payload);
    }
}

mqtt_subscribe(client, "commands/device-001", QOS_1, mqtt_message_handler);

HTTP requires one of the following approaches:

  • Polling: Periodic requests, wastes bandwidth
  • Long Polling: Occupies connections
  • WebSocket: Additional complexity

Offline Messages

MQTT supports offline message caching:

// Set Clean Session = false, Broker will retain offline messages
mqtt_connect_options opts = {
    .client_id = "device-001",
    .clean_session = false,  // Retain session state
};

// Using Retained Message, new subscribers receive the last message
mqtt_publish(client, "status/device-001", "online", QOS_1, true);

Implementation Examples

ESP32 MQTT Client

#include "mqtt_client.h"

static esp_mqtt_client_handle_t mqtt_client;

// MQTT event handler
static void mqtt_event_handler(void *args, esp_event_base_t base,
                                int32_t event_id, void *event_data) {
    esp_mqtt_event_handle_t event = event_data;

    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI(TAG, "MQTT connected");
            // Subscribe to command topic
            esp_mqtt_client_subscribe(mqtt_client, "commands/#", 1);
            break;

        case MQTT_EVENT_DATA:
            ESP_LOGI(TAG, "Message received: %.*s", event->data_len, event->data);
            process_message(event->topic, event->data);
            break;

        case MQTT_EVENT_DISCONNECTED:
            ESP_LOGW(TAG, "MQTT disconnected, auto-reconnecting...");
            break;
    }
}

void mqtt_init(void) {
    esp_mqtt_client_config_t config = {
        .broker.address.uri = "mqtts://broker.example.com",
        .credentials.client_id = "esp32-device-001",
        .session.keepalive = 60,
    };

    mqtt_client = esp_mqtt_client_init(&config);
    esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID,
                                    mqtt_event_handler, NULL);
    esp_mqtt_client_start(mqtt_client);
}

// Publish sensor data
void publish_sensor_data(float temp, float humidity) {
    char payload[128];
    snprintf(payload, sizeof(payload),
             "{\"temperature\":%.2f,\"humidity\":%.2f,\"timestamp\":%lld}",
             temp, humidity, esp_timer_get_time() / 1000);

    esp_mqtt_client_publish(mqtt_client, "sensors/esp32-001",
                            payload, 0, 1, 0);
}

Node.js MQTT Broker Side

const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://broker.example.com');

// Subscribe to all sensor data
client.on('connect', () => {
  client.subscribe('sensors/#', (err) => {
    if (!err) console.log('Subscribed to sensors topic');
  });
});

// Handle received messages
client.on('message', (topic, message) => {
  const data = JSON.parse(message.toString());
  console.log(`[${topic}] Temperature: ${data.temperature}°C`);

  // Save to database
  saveToDatabase(topic, data);

  // Check if alert is needed
  if (data.temperature > 30) {
    client.publish('alerts/high-temp', JSON.stringify({
      device: topic.split('/')[1],
      temperature: data.temperature,
    }));
  }
});

Selection Recommendations

When to Choose MQTT

  1. Frequent small data transmissions: Sensors reporting every second or minute
  2. Battery-powered devices: Need to minimize wireless transmission
  3. Real-time push required: Remote control, alert notifications
  4. Unstable networks: QoS guarantees message delivery
  5. Large device fleets: Tens of thousands of devices connected simultaneously

When to Choose HTTP

  1. Infrequent data uploads: Reporting a few times per day
  2. Large data transfers: Firmware updates, log uploads
  3. Web service integration: Using existing REST APIs
  4. Simple implementation: No need to deploy an additional Broker
  5. Firewall restrictions: Only ports 80/443 are open

Hybrid Architecture

Many systems use both protocols simultaneously:

┌─────────────────────────────────────────────────────┐
│                    Cloud Services                    │
│  ┌─────────────┐         ┌─────────────┐           │
│  │ MQTT Broker │         │ REST API    │           │
│  │ (Real-time  │         │ (Query/     │           │
│  │  data)      │         │  Config)    │           │
│  └──────┬──────┘         └──────┬──────┘           │
└─────────┼───────────────────────┼───────────────────┘
          │                       │
     MQTT │                  HTTP │
          ▼                       ▼
┌─────────────────────────────────────────────────────┐
│                    IoT Devices                       │
│  - Real-time sensor data → MQTT                     │
│  - Firmware updates → HTTP                          │
│  - Configuration changes → HTTP                     │
└─────────────────────────────────────────────────────┘

Conclusion

Both MQTT and HTTP have their strengths. When choosing, consider:

Consideration MQTT is Better HTTP is Better
Transmission Frequency High frequency Low frequency
Data Size Small payloads Large payloads
Real-time Requirements Required Not required
Power Budget Constrained Sufficient
Infrastructure Can deploy Broker Use existing services

If you are planning an IoT project, feel free to contact us to discuss the most suitable communication architecture.

$ tail -n 1 /var/log/bashcat/posts

More from the workshop.