MQTT vs HTTP is usually the first protocol decision in an IoT project, and getting it wrong shows up later as drained batteries, laggy dashboards or a server buried in polling requests. This guide compares the two on overhead, push versus poll, power use and connection model, then gives you a benchmark script so you can measure the difference on your own network rather than taking anyone's word for it.
Two Different Communication Models
HTTP is a request/response protocol. A client opens a connection, sends a request with a method, path and headers, and the server answers. The server cannot speak first. If a device needs to know whether a new command is waiting, it has to ask, again and again.
MQTT is a publish/subscribe protocol. Every client keeps one long-lived TCP connection to a broker, publishes messages to topics and subscribes to the topics it cares about. The broker pushes matching messages the moment they arrive. Publishers and subscribers never address each other directly, which is what lets one sensor reading reach a dashboard, a database writer and an alerting service at once. If you want to see what sits in the middle, read what an MQTT broker does.
That single difference, who initiates the conversation, drives almost every other trade-off below.
MQTT vs HTTP at a Glance
| Aspect | HTTP (REST) | MQTT |
|---|---|---|
| Pattern | Request/response, client always initiates | Publish/subscribe through a broker |
| Connection | Short-lived or keep-alive per client-server pair | One persistent TCP connection per client |
| Server-to-device push | Not native (polling, long polling, SSE, WebSocket) | Native: broker pushes on publish |
| Per-message overhead | Request line plus text headers, often hundreds of bytes | 2-byte minimum fixed header plus topic |
| Fan-out | Sender must call each receiver | Broker delivers to every matching subscriber |
| Delivery guarantees | Application-defined retries | QoS 0, 1, 2 built in |
| Offline detection | Infer from missing requests | Keep alive and Last Will |
| Last-known value | Query an API | Retained messages |
| Tooling | Universal: browsers, proxies, CDNs, API gateways | Broker plus MQTT client libraries |
| Best at | CRUD, file transfer, public APIs, one-off calls | Telemetry, commands, live state, many devices |
Overhead: Bytes on the Wire
Every HTTP request carries a request line, a Host header and usually content type, content length, authorization, user agent and more. All of it is text and all of it is sent again with every request. For a 20-byte sensor reading, the headers can easily be ten times larger than the data.
An MQTT PUBLISH packet has a fixed header as small as 2 bytes, the topic name and the payload. Authentication happens once, at CONNECT. After that, each reading costs little more than its topic and its data. MQTT 5 can shrink it further with topic aliases, which replace a long topic string with a small integer.
TLS changes the picture for both. The handshake is expensive, and HTTP clients that open a new TLS connection per request pay it every time. MQTT pays it once per connection. HTTP keep-alive and HTTP/2 reduce the gap, but many constrained HTTP clients do not use them.
Push vs Poll
If the cloud needs to send a command to a device, HTTP gives you three choices: poll frequently and waste bandwidth, poll rarely and accept latency, or bolt on a second channel such as WebSocket or server-sent events. MQTT just delivers. A device subscribed to devices/pump-7/cmd receives a command as soon as it is published, typically within the network round trip.
Polling also scales badly on the server. A thousand devices polling every five seconds means hundreds of requests per second whether or not anything changed. With MQTT the broker is idle until there is something to say.
Battery and Network Impact
For battery devices, the radio is usually the dominant power cost, and what matters is how often and how long it is on. HTTP polling wakes the radio on a schedule, opens a connection, possibly negotiates TLS, sends headers and waits for a reply. MQTT keeps a connection open with small PINGREQ packets at the keep alive interval and otherwise only transmits real data.
That does not make MQTT automatically better for every battery device. A sensor that wakes once an hour, sends one reading and sleeps does not benefit from a persistent connection, and a single HTTP POST may be simpler. The persistent-connection model pays off when devices send frequently, need to receive commands, or must report online status. On cellular links, where every byte and every connection setup costs money, smaller packets and fewer handshakes add up quickly.
Run Your Own MQTT vs HTTP Benchmark
Numbers depend on your network, TLS settings and library, so measure. The script below sends 200 small JSON readings over MQTT to the free public MQTT broker and 200 over HTTP POST to a local test server, then prints the elapsed time for each. Install the two dependencies first.
pip install "paho-mqtt>=2.0" requests
import json
import threading
import time
import uuid
from http.server import BaseHTTPRequestHandler, HTTPServer
import paho.mqtt.client as mqtt
import requests
N = 200
PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:8]}"
reading = json.dumps({"device": "bench-1", "temp": 21.7, "hum": 48})
# --- Minimal local HTTP endpoint ---
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
self.rfile.read(int(self.headers["Content-Length"]))
self.send_response(204)
self.end_headers()
def log_message(self, *args):
pass
server = HTTPServer(("127.0.0.1", 8080), Handler)
threading.Thread(target=server.serve_forever, daemon=True).start()
# --- HTTP: one POST per reading, new connection each time ---
start = time.perf_counter()
for _ in range(N):
requests.post("http://127.0.0.1:8080/telemetry", data=reading,
headers={"Content-Type": "application/json"})
http_new = time.perf_counter() - start
# --- HTTP: reuse one keep-alive session ---
session = requests.Session()
start = time.perf_counter()
for _ in range(N):
session.post("http://127.0.0.1:8080/telemetry", data=reading,
headers={"Content-Type": "application/json"})
http_keepalive = time.perf_counter() - start
# --- MQTT: one connection, QoS 1, wait for every PUBACK ---
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"bench-{uuid.uuid4().hex[:8]}")
client.connect("broker.connectmq.com", 1883, keepalive=30)
client.loop_start()
start = time.perf_counter()
for _ in range(N):
info = client.publish(f"{PREFIX}/telemetry", reading, qos=1)
info.wait_for_publish()
time.sleep(0.11) # stay under the public broker's 10 msg/s per client
mqtt_elapsed = time.perf_counter() - start - N * 0.11
client.loop_stop()
client.disconnect()
server.shutdown()
print(f"HTTP new connection : {http_new:.2f}s")
print(f"HTTP keep-alive : {http_keepalive:.2f}s")
print(f"MQTT QoS 1 (net) : {mqtt_elapsed:.2f}s")
Two caveats keep the comparison honest. The HTTP server runs on localhost, so it has no internet round trip, while the MQTT broker is remote; point the HTTP test at a real remote endpoint if you want a like-for-like latency test. And the public broker rate-limits each client to 10 messages per second, so the script sleeps between publishes and subtracts that time. For byte counts rather than time, run the same script under Wireshark and compare total bytes per reading. That is usually where the difference is most striking.
When HTTP Is the Right Choice
HTTP remains the better tool in several situations:
- Infrequent uploads from devices that sleep for long periods and never need commands.
- Large transfers such as firmware images, logs or camera snapshots, where HTTP range requests, CDNs and caching shine.
- Public and partner APIs, where every developer and tool already speaks REST.
- Restrictive networks that only allow outbound HTTPS. Even here, MQTT over secure WebSocket is often allowed, because it starts as an ordinary HTTPS upgrade.
Many real systems use both: MQTT for telemetry, commands and status, HTTP for provisioning, firmware downloads and back-office APIs. A small bridge service that subscribes to MQTT and exposes a REST endpoint is a common pattern; the MQTT to REST API with Flask guide shows one.
When MQTT Is the Right Choice
Choose MQTT when devices report often, when the cloud must reach devices quickly, when several consumers need the same data, or when you need to know which devices are online. Retained messages give late joiners the current state, Last Will publishes an offline status when a device drops, and QoS levels let you trade overhead for delivery guarantees per message. The MQTT publish/subscribe model article explains why decoupling producers from consumers matters as a system grows.
The cost of MQTT is that you need a broker, and running one reliably is real operational work, from TLS certificates to connection limits. ConnectMQ handles that side for you. That is the main reason teams pick a managed MQTT broker rather than maintaining their own. If you are still building fundamentals, the MQTT tutorial covers topics, QoS and sessions step by step.
Decision Checklist
- Does the server need to push data or commands to devices? If yes, lean MQTT.
- Do devices send data more than a few times per hour? If yes, lean MQTT.
- Do several services consume the same data? If yes, lean MQTT.
- Is the payload large or the exchange a one-off file transfer? If yes, use HTTP.
- Must third parties integrate using standard web tooling? Expose HTTP at the edge of your system.
- Is online/offline status important? MQTT gives you keep alive and Last Will for free.
Try MQTT on ConnectMQ
The fastest way to settle MQTT vs HTTP for your project is to run your own device against a real broker. ConnectMQ gives you a private, TLS-secured broker on ports 8883 and 8084 with generated credentials, an in-browser MQTT client and a live topic explorer. Start on the free Serverless plan at app.connectmq.com, no credit card required, and compare the results with your current HTTP setup.
Frequently Asked Questions
Is MQTT faster than HTTP?
For frequent small messages, usually yes, because MQTT reuses one connection and sends far smaller headers. For a single large transfer the difference is small and HTTP tooling is often better.
Can MQTT replace a REST API?
It can replace polling-based device endpoints, but REST is still the better fit for public APIs, CRUD operations and file transfers. Most IoT platforms use both.
Does MQTT use less battery than HTTP?
When devices communicate often or need to receive commands, typically yes, since there are no repeated handshakes or polling. Devices that wake rarely to send one reading may see little benefit.
Can browsers use MQTT like they use HTTP?
Yes, through MQTT over WebSocket. Browser clients connect to a URL such as wss://broker.connectmq.com:8084/mqtt using a library like MQTT.js.



