MQTT Fundamentals

MQTT Latency Explained: What Affects Round-Trip Time and How to Measure It

Where does MQTT latency come from? This guide breaks down network, TLS, QoS and broker processing delays and gives you a Python script to measure round-trip time against broker.connectmq.com.

Illustration of MQTT latency as a stopwatch measuring a message travelling from a device to a cloud broker and back
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

MQTT latency is the time between a publisher sending a message and a subscriber receiving it, and for most IoT systems it is dominated by things outside the protocol itself. This guide breaks down every component of round-trip time, explains which knobs actually matter, and gives you a small Python script to measure latency from your own network against a live broker.

What "Latency" Means in MQTT

People use the word for several different measurements, so be precise before you optimize:

  • One-way latency: publisher to subscriber. Hard to measure accurately because the two clocks are on different machines.
  • Round-trip time (RTT): a client publishes to a topic it is also subscribed to and measures how long until the message comes back. One clock, so the number is trustworthy. This is what the script below measures.
  • Connect latency: time from opening a socket to receiving CONNACK. Relevant for devices that wake, connect, publish and sleep.
  • Acknowledgement latency: time from PUBLISH to PUBACK at QoS 1, which tells you when the broker has taken responsibility for the message.

For devices that keep a connection open (the normal MQTT pattern), round-trip time is the most useful single number.

The Components of MQTT Latency

A message from a sensor to a dashboard passes through several stages. Each adds delay:

Stage What happens Typical influence Main lever
Client stack Library queues, serializes, writes to socket Small, but large on busy microcontrollers Non-blocking loop, avoid long delay() calls
Last-mile network Wi-Fi, cellular, satellite access Often the largest and most variable part Better link, cellular signal, wired gateway
Internet path Routing to the broker's region Grows with physical distance Broker region close to devices
TLS Encryption per packet, handshake per connect Handshake costs extra round trips once; per-packet cost is small Keep connections long-lived
QoS handshake PUBACK or 4-step QoS 2 flow Does not delay delivery much, but limits throughput Choose QoS per data type
Broker processing Auth, topic matching, fan-out Usually small on a healthy broker Avoid huge fan-outs and hot topics
Subscriber side Same path in reverse, plus app processing Mirrors the publisher side Lightweight callbacks

Network distance

Light in fiber is fast, but not instantaneous, and real routes are not straight lines. A device in Istanbul talking to a broker in another continent will always see a higher baseline than one talking to a broker in its own region. No protocol setting can remove this; only broker placement can.

TLS overhead

The TLS handshake adds round trips when the connection opens. After that, symmetric encryption costs very little on modern CPUs and only a modest amount on chips like the ESP32. Because MQTT clients normally stay connected for hours or days, TLS mostly affects connect latency, not steady-state message latency. That is why "TLS is slow" is rarely a good reason to use port 1883; see MQTT ports explained for the trade-offs.

QoS level

This is the most misunderstood part. At QoS 0, the broker forwards immediately. At QoS 1, the broker also forwards immediately on receipt, and the PUBACK travels back in parallel, so delivery latency is similar to QoS 0 on a healthy link. QoS 2 adds a four-step handshake; depending on the broker implementation, forwarding can happen after the first or second step. The bigger effect of higher QoS is on throughput and on what happens during packet loss: retransmissions add latency when the network misbehaves. The MQTT QoS levels guide covers the flows in detail.

Nagle, buffering and the client loop

Some stacks delay small writes to combine them. Many MQTT libraries disable Nagle's algorithm, but embedded stacks and custom sockets may not. On microcontrollers, a main loop that calls client.loop() only once per second adds up to a second of latency to incoming messages, regardless of how fast the network is.

Keep-alive and reconnects

Keep-alive does not affect latency on a healthy connection, but it decides how fast a dead connection is detected. A silently dropped link with a 300-second keep-alive can mean minutes before the client reconnects, and every message in that window is late.

Measure MQTT Latency Yourself

The script below connects to the public MQTT test broker at broker.connectmq.com, subscribes to a unique topic, publishes timestamped messages to it, and computes round-trip statistics. It stays under the public broker's limit of 10 messages per second per client by sending two per second.

# mqtt_rtt.py - measure MQTT round-trip latency
# pip install "paho-mqtt>=2.0"
import json
import statistics
import sys
import threading
import time
import uuid

import paho.mqtt.client as mqtt

HOST = "broker.connectmq.com"
USE_TLS = "--tls" in sys.argv
PORT = 8883 if USE_TLS else 1883
QOS = 1
SAMPLES = 50
INTERVAL = 0.5  # seconds between publishes (2 msg/s)

run_id = uuid.uuid4().hex[:8]
topic = f"connectmq/demo/{run_id}/rtt"
rtts = []
subscribed = threading.Event()
done = threading.Event()


def on_connect(client, userdata, flags, reason_code, properties):
    print(f"Connected to {HOST}:{PORT} -> {reason_code}")
    client.subscribe(topic, qos=QOS)


def on_subscribe(client, userdata, mid, reason_code_list, properties):
    subscribed.set()


def on_message(client, userdata, msg):
    received = time.perf_counter()
    data = json.loads(msg.payload)
    rtts.append((received - data["t"]) * 1000.0)
    if len(rtts) >= SAMPLES:
        done.set()


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"rtt-{run_id}")
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message
if USE_TLS:
    client.tls_set()  # uses the system CA store

t0 = time.perf_counter()
client.connect(HOST, PORT, keepalive=60)
client.loop_start()
if not subscribed.wait(10):
    sys.exit("Subscribe timed out")
print(f"Connect + subscribe took {(time.perf_counter() - t0) * 1000:.1f} ms")

for seq in range(SAMPLES):
    payload = json.dumps({"seq": seq, "t": time.perf_counter()})
    client.publish(topic, payload, qos=QOS)
    time.sleep(INTERVAL)

done.wait(10)
client.loop_stop()
client.disconnect()

if not rtts:
    sys.exit("No messages received")

rtts.sort()
p95 = rtts[int(len(rtts) * 0.95) - 1]
print(f"samples={len(rtts)} lost={SAMPLES - len(rtts)}")
print(f"min={rtts[0]:.1f} ms  median={statistics.median(rtts):.1f} ms  "
      f"p95={p95:.1f} ms  max={rtts[-1]:.1f} ms")

Run it twice and compare:

python mqtt_rtt.py         # plain TCP on 1883
python mqtt_rtt.py --tls   # TLS on 8883

Reading the results

  1. Minimum approximates the best-case path: network plus broker with nothing in the way. It is your floor.
  2. Median is what users typically experience.
  3. p95 and max reveal jitter from Wi-Fi retries, cellular scheduling or congested links. For control loops and alarms, these matter more than the median.
  4. Connect + subscribe shows the TLS handshake cost. Expect it to be noticeably higher with --tls, while the per-message median stays close to the plain TCP run.
  5. Lost samples at QoS 1 usually mean the script ended before late messages arrived, or the connection dropped. Check the console for disconnects.

Run the test from where your devices actually live (the plant network, a cellular modem, a home router), not only from your office. The difference is often the most valuable finding.

Practical Ways to Reduce MQTT Latency

  1. Keep connections open. Connect once, publish many times. Reconnecting per message pays the TCP and TLS handshake every time.
  2. Choose a broker region near your devices. Distance sets the floor.
  3. Pick QoS per data type. High-rate telemetry where the next sample replaces the last can use QoS 0; commands and alarms deserve QoS 1.
  4. Keep payloads compact. Large JSON documents take longer to send on slow links. Consider binary encodings for high-rate data and MQTT 5 topic aliases to shorten repeated topic names.
  5. Service the client loop often. On Arduino or ESP32, call loop() every iteration and avoid blocking delays.
  6. Tune keep-alive to detect dead links quickly (30 to 60 seconds is common) without wasting bandwidth.
  7. Avoid unnecessary hops. Every bridge, gateway or Node-RED relay in the path adds its own processing and queueing.
  8. Make subscriber callbacks fast. Hand heavy work to a worker thread or queue so the network loop is not blocked.

Troubleshooting High or Spiky Latency

Symptom Likely cause What to check
High minimum RTT Distance to broker or slow access network Ping and traceroute to the broker host
Good median, terrible p95 Wi-Fi retries, cellular scheduling Test on a wired link to compare
Latency grows over time Subscriber cannot keep up, messages queue Callback duration and inflight counts
Periodic multi-second gaps Blocking code in the client loop Long sleep or synchronous I/O in callbacks
Spikes only on reconnect TLS handshake plus session resume Connection stability and keep-alive
Throttling on the public broker Rate limit of 10 msg/s per client Lower publish rate or use a private broker

From Measurement to Production

The public broker is shared, so treat its numbers as indicative of your network path rather than as a benchmark. For production traffic, a managed MQTT broker such as ConnectMQ gives you a private, authenticated endpoint on 8883 and 8084 without the public rate limits; plan details are in the cloud MQTT broker guide. To repeat the test against your own ConnectMQ broker, add client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD"), set the client ID to YOUR_CLIENT_ID, and run with --tls. For broader protocol background, see the MQTT tutorial and how MQTT works.

Get Started with ConnectMQ

Create a free Serverless broker at app.connectmq.com, no credit card needed, and point the latency script at it in two lines. ConnectMQ's in-browser client and live topic explorer help you see exactly when each message arrives.

Frequently Asked Questions

What is a good MQTT latency?

It depends on distance and access network. Compare your minimum RTT with a plain network ping to the broker host; if MQTT adds only a little on top, the broker is not your bottleneck.

Does QoS 1 make MQTT slower than QoS 0?

On a healthy link, delivery latency is similar because the broker forwards before the PUBACK completes. QoS 1 mainly adds overhead when packets are lost and must be resent.

Does TLS increase MQTT latency?

TLS adds handshake time when connecting, but on a long-lived connection the per-message overhead is small. Keeping connections open is the best way to minimize its impact.

Why measure round-trip instead of one-way latency?

Round-trip uses a single clock, so it avoids errors from unsynchronized clocks on publisher and subscriber machines.

Related articles

Why Your MQTT Client Keeps Disconnecting (and How to Fix It)

Reconnect loops are one of the most common MQTT problems. Learn the five usual causes, from duplicate client IDs to keep alive timeouts and oversized packets, and follow a diagnosis flow that pinpoints yours.

8 min read

Who Invented MQTT? The History from Oil Pipelines to IoT

MQTT was invented in 1999 by Andy Stanford-Clark of IBM and Arlen Nipper of Arcom to monitor oil pipelines over satellite. Follow its path to open source, OASIS, ISO and today's managed cloud brokers.

7 min read

MQTT Maximum Message Size: Limits and Large Payload Strategies

MQTT can technically carry a 256 MB packet, but brokers, client libraries and devices impose far lower limits. Learn where the real limits are, what happens when you exceed them, and how to send large payloads.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.