Estimating MQTT messages per second is the most useful sizing exercise you can do before choosing a broker plan, and it takes less than an hour. This guide shows you how to calculate inbound and outbound message rates for your fleet, account for peaks and protocol overhead, measure real traffic with a short script, and translate the numbers into a plan decision.
Inbound, Outbound and Why Both Matter
A broker handles two message flows:
- Inbound: messages published by clients to the broker.
- Outbound: copies the broker delivers to matching subscribers.
If every message has exactly one subscriber, the two are equal. In real systems they rarely are. A telemetry message read by a dashboard, a historian and an alerting service produces three outbound deliveries. A command sent to one device produces one. A wildcard subscriber such as a debugging tool on # receives everything. Outbound is often the larger number, so always estimate both.
The Core Formulas
You only need three:
- Inbound rate (msg/s) = number of publishers x messages per publisher per second
- Outbound rate (msg/s) = inbound rate on each topic x number of matching subscribers, summed across topics
- Bandwidth (bytes/s) = (inbound + outbound) x average message size, plus protocol and TLS overhead
Message size here means the MQTT payload plus the topic string and a few bytes of fixed header. For small telemetry, the topic can be as large as the payload, which is one reason MQTT 5 topic aliases exist.
Remember QoS when reasoning about packets rather than messages. QoS 0 sends one packet per delivery. QoS 1 adds a PUBACK for every publish in each direction. QoS 2 uses a four-packet exchange. The message count does not change, but the packet count and broker work do.
A Worked Example
Consider a hypothetical facility with three kinds of publishers. These figures are illustrative, not measurements.
| Publisher group | Count | Publish interval | Inbound msg/s | Subscribers per message | Outbound msg/s |
|---|---|---|---|---|---|
| Environment sensors | 120 | every 60 s | 2.0 | 2 (dashboard, historian) | 4.0 |
| Machine gateways | 15 | every 1 s | 15.0 | 3 (dashboard, historian, alerts) | 45.0 |
| Device status | 135 | on change, about every 10 min | 0.2 | 1 (monitor) | 0.2 |
| Total | 270 | 17.2 | 49.2 |
Three observations come out of a table like this almost every time:
- Fifteen fast gateways generate most of the traffic, while 120 slow sensors barely register.
- Outbound is nearly three times inbound because of fan-out.
- The connection count, 270 clients plus the backend subscribers, may be the limit you hit first, long before message rate becomes a concern.
Planning for Peaks, Not Averages
Averages hide the moments that cause trouble. Add explicit allowances for:
- Reconnect floods. After an outage, devices reconnect together and many flush buffered readings at once.
- Synchronized timers. Devices that boot at the same time and publish every 60 seconds will publish in the same second. Add random jitter to the first publish.
- Event bursts. Alarms often cascade: one fault triggers dozens of related alerts.
- Shift or schedule changes. Production lines that start together create step changes in traffic.
- Debug sessions. Someone subscribing to
#in a desktop tool adds a full copy of all traffic.
A simple rule of thumb is to size for a peak several times your average and verify that clients smooth their bursts with rate limiting and jitter.
Measuring Real Message Rates
Estimates are a starting point; measurement keeps you honest. The script below subscribes to a topic filter and prints messages per second and bytes per second every five seconds. Point it at your own broker with production credentials, or try it on the public MQTT test broker with a unique topic prefix.
# rate_meter.py - measure MQTT messages per second on a topic filter
import sys
import threading
import time
import paho.mqtt.client as mqtt
HOST = "broker.connectmq.com"
FILTER = sys.argv[1] if len(sys.argv) > 1 else "connectmq/demo/r8m2/#"
WINDOW = 5
lock = threading.Lock()
count = 0
nbytes = 0
per_topic = {}
def on_connect(client, userdata, flags, reason_code, properties):
print("connected:", reason_code, "- measuring", FILTER)
client.subscribe(FILTER, qos=0)
def on_message(client, userdata, msg):
global count, nbytes
with lock:
count += 1
nbytes += len(msg.payload) + len(msg.topic)
per_topic[msg.topic] = per_topic.get(msg.topic, 0) + 1
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id="rate-meter-r8m2", protocol=mqtt.MQTTv5)
# For your private broker, uncomment these and use port 8883:
# client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
# client.tls_set()
client.on_connect = on_connect
client.on_message = on_message
client.connect(HOST, 1883)
client.loop_start()
while True:
time.sleep(WINDOW)
with lock:
msgs, size, top = count, nbytes, sorted(per_topic.items(), key=lambda kv: -kv[1])[:3]
count = nbytes = 0
per_topic.clear()
print(f"{msgs / WINDOW:8.1f} msg/s {size / WINDOW / 1024:8.2f} KB/s top: {top}")
To generate test traffic in another terminal:
for i in $(seq 1 200); do
mosquitto_pub -h broker.connectmq.com -p 1883 -i rate-pub-r8m2 \
-t "connectmq/demo/r8m2/sensor/$((i % 5))" -m "{\"v\":$i}"
sleep 0.2
done
The pacing matters: the public broker allows 10 messages per second per client, so keep test publishers below that. When you measure a production broker, run the meter as a separate client with its own credentials, and measure during a busy period, not overnight.
Mapping Throughput to a Broker Plan
Once you have numbers, map them to plan limits. On ConnectMQ, the plan limits you need to check are:
| Plan | Connections | Max QoS | Max message size | Shared subscriptions |
|---|---|---|---|---|
| Serverless (Free) | Up to 25 | 1 | 256 KB | No |
| Serverless (Paid) | Up to 1,000 | 2 | 1 MB | Yes |
| Dedicated | Isolated cluster sized with you | Discussed with the team | Discussed with the team | Discussed with the team |
| BYOC | In your cloud account, sized with you | Discussed with the team | Discussed with the team | Discussed with the team |
How to read the table against your estimate:
- Connections first. Add publishers, subscribers, dashboards and tools. That number usually decides between Free and Paid Serverless.
- Largest message second. If any message, including a backlog batch, exceeds 256 KB, you need the paid plan or smaller batches.
- QoS third. If any flow requires exactly-once delivery, you need QoS 2.
- Consumer scaling fourth. If one backend subscriber cannot keep up with your outbound rate, you need shared subscriptions to split the load across instances.
- Isolation last. If your throughput is high and sustained, or you cannot accept other tenants' activity affecting yours, discuss Dedicated or BYOC and share your inbound, outbound and peak numbers with the team.
For quota behavior when limits are reached, read MQTT broker connection quotas. For the broader picture of growing a deployment, see how to scale an MQTT broker and how many connections an MQTT broker can handle.
Ways to Reduce Message Rate
If your estimate is higher than you would like, these techniques reduce traffic without losing information:
- Report by exception. Publish when a value changes beyond a deadband rather than on a fixed timer.
- Batch samples. Send one message with ten readings instead of ten messages.
- Downsample at the edge. Publish one-second averages instead of raw high-frequency samples when consumers do not need the raw data.
- Narrow subscriptions. Remove unnecessary
#subscribers, which multiply outbound traffic. - Use compact payloads. Shorter JSON keys or binary encodings such as Protobuf reduce bytes per message.
- Use topic aliases. On MQTT 5, aliases cut repeated long topic strings to a small integer.
Get Started with ConnectMQ
ConnectMQ is a managed MQTT broker with clear per-plan limits, a live topic explorer and a dashboard for watching traffic as it flows. Create a free Serverless broker at app.connectmq.com, no credit card required, run the rate meter against it, and pick the plan your numbers point to. For the full range of hosting options, see the cloud MQTT broker guide.
Frequently Asked Questions
How do I calculate MQTT messages per second?
Multiply the number of publishers by how often each publishes to get inbound rate, then multiply each topic's inbound rate by its number of subscribers to get outbound rate. Add an allowance for peaks.
Why is outbound traffic higher than inbound?
Each published message is delivered to every matching subscriber, so a message read by three services counts three times outbound. Wildcard subscribers increase this further.
Does QoS affect messages per second?
QoS does not change how many messages you send, but QoS 1 and 2 add acknowledgement packets and broker work for each message. Use QoS 0 for high-rate telemetry where the next sample replaces the last.
What message rate does the ConnectMQ public broker allow?
The public test broker allows 10 messages per second per client, with 64 KB per message. Private plans are defined by connection count, message size and QoS limits, so check those against your estimate.



