Managed MQTT Cloud

MQTT Broker Connection Quotas: Connections, Message Rates and Payload Limits

Managed MQTT brokers enforce quotas on connections, message rates, payload sizes and subscriptions. Learn how each one works, how brokers signal violations, and how to build clients that respect them.

MQTT broker connection quotas illustration with gauges for connections, message rate and payload size on a cloud broker
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 broker connection quotas decide how many clients you can attach, how fast they may publish and how large each message can be. This guide explains every common quota on a managed broker, how MQTT 3.1.1 and MQTT 5 brokers signal that you have hit one, and how to write clients that stay comfortably inside the limits of your plan.

Why Managed Brokers Enforce Quotas

A managed broker is shared infrastructure, even when you have a dedicated cluster. Memory, CPU, network bandwidth and file descriptors are finite, and a single misbehaving client, such as firmware stuck in a tight publish loop or a reconnect storm after a Wi-Fi outage, can degrade service for everyone else on the same machines. Quotas turn those finite resources into explicit, predictable limits.

On a multi-tenant service, quotas are also how isolation works in practice. ConnectMQ, for example, applies per-plan quotas, flood protection and IP blocking after repeated failed logins so that one tenant's problem stays that tenant's problem. If you are new to the model, our explainer on what an MQTT broker does covers the basics of how clients and brokers interact.

The Common MQTT Broker Quotas

Most providers enforce some combination of the following. Names differ, but the concepts are the same everywhere.

Quota What it counts Typical symptom when exceeded
Concurrent connections Open client sessions at the same moment New CONNECT is refused
Connection rate New connections per second or minute Reconnects fail during storms
Message rate Publishes per second per client or account Client is throttled or disconnected
Maximum payload size Bytes in a single PUBLISH Publish rejected or connection closed
Subscriptions per client Topic filters a client may hold SUBACK returns a failure code
Topic depth Number of levels separated by / Publish or subscribe rejected
Highest QoS 0, 1 or 2 Subscription granted at a lower QoS
Session expiry How long the broker keeps an offline session Queued messages lost after expiry

Real plan limits as an example

Here is how ConnectMQ sets its limits by plan:

  • Serverless (Free): up to 25 connections, QoS up to 1, messages up to 256 KB.
  • Serverless (Paid): up to 1,000 connections, QoS 2, messages up to 1 MB, shared subscriptions.
  • Dedicated, BYOC and Self Managed Enterprise: isolated deployments sized for your workload.
  • Public test broker (broker.connectmq.com): 64 KB per message, 10 messages per second per client, 10 subscriptions per client, 8 topic levels, QoS 0 to 2 and session expiry up to 30 minutes.

How Brokers Signal That You Hit a Quota

This is where the protocol version matters a great deal.

MQTT 3.1.1: guessing from disconnects

MQTT 3.1.1 has only a handful of CONNACK return codes and no way for the broker to explain a disconnect. When a 3.1.1 client exceeds a limit, the broker usually just closes the TCP connection. The client sees a generic "connection lost" and reconnects, often hitting the same limit again. Diagnosing quota problems on 3.1.1 means correlating client logs with whatever the provider's console shows.

MQTT 5: explicit reason codes

MQTT 5 added reason codes to CONNACK, PUBACK, SUBACK and DISCONNECT, which makes quota problems visible to the client. The ones you will meet most often are defined in the OASIS MQTT 5.0 specification:

Code Name Meaning in practice
0x87 Not authorized Credentials or client ID do not allow this action
0x8E Session taken over Another client connected with the same client ID
0x95 Packet too large Payload exceeds the maximum packet size
0x96 Message rate too high Publish rate exceeded
0x97 Quota exceeded An implementation or plan quota was hit
0x9F Connection rate exceeded Too many connection attempts

ConnectMQ supports MQTT 5 reason codes, including 0x97 quota exceeded, so a client using MQTT 5 can log a precise cause instead of a vague disconnect. That alone is a strong reason to use MQTT 5 for new projects; see MQTT 5 features for the rest.

MQTT 5 brokers can also advertise limits up front in CONNACK properties such as Maximum Packet Size, Receive Maximum, Topic Alias Maximum and Maximum QoS. A well-written client reads them and adapts.

Designing Clients That Stay Inside Their Quotas

The best quota strategy is a client that never gets near the limit. These practices prevent most quota incidents.

Read the broker's limits at connect time

The Python example below connects with paho-mqtt 2.x over TLS, prints the limits the broker advertises and logs reason codes on disconnect.

import paho.mqtt.client as mqtt

LIMIT_PROPS = ("MaximumPacketSize", "ReceiveMaximum",
               "TopicAliasMaximum", "MaximumQoS", "SharedSubscriptionAvailable")

def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code.is_failure:
        print("connect refused:", reason_code)
        return
    print("connected")
    for name in LIMIT_PROPS:
        value = getattr(properties, name, None)
        if value is not None:
            print(f"  broker limit {name} = {value}")

def on_disconnect(client, userdata, flags, reason_code, properties):
    print("disconnected:", reason_code)
    if reason_code == "Quota exceeded":
        print("plan quota hit; back off and alert an operator")

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id="YOUR_CLIENT_ID", protocol=mqtt.MQTTv5)
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set()
client.reconnect_delay_set(min_delay=1, max_delay=120)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.connect("broker.connectmq.com", 8883, keepalive=60)
client.loop_forever()

If you want to experiment without an account first, point the same script at the free public MQTT broker on port 1883 with a unique client ID and no credentials.

Rate-limit publishes on the client

Never rely on the broker to throttle you. A small token bucket keeps bursts under control, which matters most after a device reconnects and tries to flush a backlog.

const mqtt = require("mqtt");

const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
  clientId: "YOUR_CLIENT_ID",
  username: "YOUR_USERNAME",
  password: "YOUR_PASSWORD",
  protocolVersion: 5,
  reconnectPeriod: 5000,
});

// Token bucket: at most RATE messages per second, burst up to BURST.
const RATE = 5;
const BURST = 10;
let tokens = BURST;
setInterval(() => { tokens = Math.min(BURST, tokens + RATE); }, 1000);

const queue = [];
function enqueue(topic, payload) { queue.push({ topic, payload }); }

setInterval(() => {
  while (tokens >= 1 && queue.length > 0 && client.connected) {
    const { topic, payload } = queue.shift();
    client.publish(topic, payload, { qos: 1 });
    tokens -= 1;
  }
}, 100);

client.on("connect", () => console.log("connected"));
client.on("disconnect", (packet) => console.log("broker disconnect, reason", packet.reasonCode));

// Simulate a backlog flush after an outage.
for (let i = 0; i < 50; i++) enqueue("factory/line1/temp", JSON.stringify({ i, c: 20 + Math.random() }));

Back off with jitter on reconnect

When a site loses connectivity, hundreds of devices may reconnect within the same second. Without randomized backoff they hit the connection rate quota together, fail together and retry together. Add random jitter to every reconnect delay and cap the maximum delay at a minute or two.

Keep client IDs unique and stable

On managed brokers that bind client IDs to issued credentials, as ConnectMQ does, duplicates are a common trap. If you copy one set of credentials onto two devices, each connection kicks the other off, which MQTT 5 reports as 0x8E session taken over. The result looks like a flapping connection and quickly burns through connection-rate limits. Issue one credential set per device or service.

Batch small readings

Ten sensor values in one JSON message cost one publish instead of ten. Batching keeps message rates down and usually reduces bandwidth, provided the batch stays well under your plan's payload limit.

Use fewer, broader subscriptions

A single wildcard such as site1/+/telemetry is cheaper to manage than dozens of exact subscriptions, and it keeps you clear of per-client subscription caps.

A Quota Readiness Checklist

Before rollout, walk through this list for every client type:

  1. Count concurrent connections, including dashboards, scripts and integrations.
  2. Calculate peak publishes per second per client, not just the average.
  3. Measure the largest payload, including backlog flushes and error dumps.
  4. Confirm the QoS level each topic needs and that the plan supports it.
  5. Verify every device has its own client ID and credentials.
  6. Implement exponential backoff with jitter for reconnects.
  7. Log MQTT 5 reason codes and ship them somewhere you can search.
  8. Leave headroom: plan for roughly double your expected load so growth does not surprise you.

For the sizing math behind points 2 and 3, read estimating MQTT messages per second. If you are comparing entry-level options, our guide to the MQTT broker free tier shows how quotas differ between free plans, and the cloud MQTT broker pillar covers hosting choices more broadly.

Troubleshooting Quota Problems

  • Connections drop every few seconds: check for duplicate client IDs before anything else.
  • Large messages vanish: compare the payload size against the plan limit and the broker's Maximum Packet Size property.
  • Subscriptions silently receive nothing: inspect the SUBACK reason codes; a failure code means the filter was not accepted.
  • Everything fails after a site-wide outage: your reconnect logic lacks jitter and you are tripping connection-rate protection.
  • Unexplained disconnects on MQTT 3.1.1: switch the client to MQTT 5 temporarily to get a reason code.

Get Started with a Managed MQTT Plan

ConnectMQ publishes its plan limits clearly and reports quota problems with MQTT 5 reason codes, so you can design to them from day one. Start on the free Serverless plan at app.connectmq.com with no credit card, then step up to paid Serverless, Dedicated or BYOC as your fleet grows. If you prefer someone else to run the infrastructure entirely, a fully managed MQTT service handles patching, TLS and capacity for you.

Frequently Asked Questions

What does MQTT reason code 0x97 mean?

0x97 is "Quota exceeded" in MQTT 5. The broker is telling the client that an implementation or plan limit was reached, so the client should back off rather than retry immediately.

Do dashboards and scripts count toward connection quotas?

Yes. Every MQTT client holding an open session counts as one connection, whether it is a sensor, a Node-RED flow or a browser tab.

How do I know the maximum message size my broker accepts?

Check the plan documentation and, on MQTT 5, read the Maximum Packet Size property in CONNACK. The ConnectMQ free Serverless plan allows 256 KB and the paid Serverless plan allows 1 MB.

Why does my device keep reconnecting in a loop?

The most common cause is two clients sharing one client ID, which makes the broker disconnect the older session each time. Give every device its own credentials and client ID.

Related articles

BYOC MQTT Broker: Bring Your Own Cloud Explained

A BYOC MQTT broker runs in your cloud account but is operated by a provider. Learn how the model works, the responsibility split, and how to prepare your account for it.

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.