IoT Scalability: Millions of Devices, Message Brokers
Learn how IoT architectures scale to millions of devices: connection limits, thundering herds, broker clustering, QoS, and a worked sizing example.
Contents & prerequisites
Scaling an IoT deployment from a 50-unit pilot to a 5-million-unit fleet is not a matter of buying bigger servers. Connection handling, message routing, and state storage all hit different bottlenecks as device count grows, and the architecture decisions that worked at 50 devices (one MQTT broker, one database, synchronous REST calls) actively break at 500,000. Understanding where the limits are — and how message brokers are designed to push past them — is foundational to any IoT system architecture.
Why Scale Breaks Naive Architectures
A single device polling a REST endpoint every 30 s is trivial. The problem is multiplicative:
Total messages/sec = N_devices × (1 / reporting_interval)
At 1 million devices reporting every 30 s: 1,000,000 / 30 ≈ 33,333 msg/s sustained, before counting command/config traffic or retries. A single-instance broker or database with a practical ceiling of a few thousand transactions/sec falls over long before that. Three resources hit limits independently:
- Connection count — each device typically holds a persistent TCP/TLS session (MQTT, CoAP-over-DTLS). One broker process has a file-descriptor and memory ceiling (roughly 4–10 KB of kernel+broker memory per idle MQTT connection), so 1M devices means tens of GB of RAM just to hold sockets open, plus TLS handshake CPU cost during mass reconnect events (e.g., after a regional outage).
- Message throughput — the broker must route, filter, and often persist every message. Topic-matching cost and fan-out (one telemetry message triggering multiple subscribers: storage, rules engine, dashboard) multiply the effective load.
- State storage — device shadows/twins, last-known-values, and time-series telemetry all need writes at device scale. A relational database with row-level locks degrades non-linearly as write concurrency rises.
The Thundering Herd Problem
A specific failure mode worth naming: mass reconnect. If a broker restarts or a mobile network segment recovers from an outage, every device attempts to reconnect within seconds. This "thundering herd" produces a spike far above steady-state throughput.
Mitigations:
- Jittered backoff — each device delays reconnection by a random interval (e.g.,
base_delay × (1 + random(0,1)), capped and doubling on repeated failure) instead of retrying immediately. - Connection rate limiting at the load balancer/broker cluster ingress.
- Staggered provisioning — group devices by ID hash and stagger scheduled actions (firmware checks, cert renewal) across time windows rather than a fixed clock tick.
Horizontal Scaling: Broker Clustering
The core answer to "more devices than one machine can hold" is partitioning connections and topics across a cluster rather than one broker instance.
| Approach | How it works | Trade-off |
|---|---|---|
| Clustered broker (e.g., shared-nothing MQTT cluster) | Devices connect to any node behind a load balancer; nodes share subscription state via a distributed protocol | Adds cluster coordination overhead; subscription lookup across nodes costs latency |
| Broker-per-shard | Devices statically assigned to a shard (by device ID hash or region) | Simple, but rebalancing on node failure/growth is manual/harder |
| Bridging/federation | Independent brokers per site/region, bridged to a central broker for cross-cutting topics | Good for geographic distribution, isolates local failures |
| Managed cloud IoT broker service | Provider handles connection scaling, sharding, autoscaling internally | Least engineering effort, but per-message/per-connection billing and vendor lock-in risk |
Most production IIoT platforms combine sharding by geography/tenant with a clustered broker layer inside each shard, and a lightweight bridge for global aggregation (fleet-wide alarms, cross-region analytics).
Decoupling with a Message Broker/Queue
The single biggest architectural lever at scale is decoupling ingestion from processing. Instead of a device's message triggering synchronous downstream work (write to DB, run rules, update dashboard — all before acking the device), the broker's job is only to accept and durably queue the message; consumers pull from the queue at their own pace.
Device → MQTT broker → topic/queue → [consumer: time-series DB]
→ [consumer: rules engine]
→ [consumer: alarm service]
This gives three properties needed at scale:
- Backpressure absorption — a burst of 50,000 msg/s can be queued even if the database consumer only sustains 10,000 writes/s; the queue smooths the mismatch instead of dropping messages or blocking devices.
- Independent consumer scaling — add more instances of the slow consumer (e.g., database writer) without touching ingestion or device firmware.
- Fault isolation — if the alarm service crashes, telemetry storage keeps running; the alarm consumer resumes from its last committed offset on recovery.
QoS and Delivery Guarantees at Scale
Delivery semantics matter more as fleet size grows because retries multiply load:
| QoS level | Guarantee | Cost at scale |
|---|---|---|
| At most once (fire-and-forget) | No retry, message may be lost | Lowest broker/network load; fine for high-frequency, loss-tolerant telemetry (e.g., 1 Hz vibration samples where the next sample compensates) |
| At least once | Retried until acked, may duplicate | Requires idempotent consumers (dedupe by message ID); moderate overhead |
| Exactly once | No loss, no duplication | Requires transactional bookkeeping (offsets + dedupe store); highest broker/storage cost, reserved for billing/command traffic |
A common design pattern: telemetry uses at-most-once or at-least-once (cheap, tolerant), while commands (firmware push, actuator control) use at-least-once with idempotent handlers, since duplicated "turn on" commands are harmless but lost ones are not.
Worked Example: Sizing a Broker Tier
Assume a fleet of 2,000,000 devices, each sending one 200-byte telemetry message every 60 s, plus a fan-out of 3 (storage, rules engine, dashboard cache) per message.
- Ingestion rate:
2,000,000 / 60 ≈ 33,333 msg/sinbound. - Fan-out rate:
33,333 × 3 ≈ 100,000 msg/sbroker-to-consumer delivery. - Bandwidth (payload only):
33,333 × 200 B ≈ 6.67 MB/s ≈ 53.3 Mb/sinbound; ignoring TLS/MQTT framing overhead (roughly +20–30% in practice, so using the 53.3 Mb/s base, ≈ 64–69 Mb/s realistic). - Connections: 2,000,000 persistent sessions. At ~6 KB/connection (broker+kernel), that's
2,000,000 × 6 KB ≈ 12 GBjust for socket/session state — meaning a single-node broker is not viable; a cluster of, say, 20 nodes gives ~100,000 connections/node, a comfortable per-node target for common MQTT broker implementations. - Check: if the storage consumer can sustain 15,000 writes/s per instance, the 33,333 msg/s ingest rate needs at least
33,333 / 15,000 ≈ 3(round up to a headroom of 4–5) parallel writer instances to keep queue lag near zero under steady state — confirming decoupled consumer scaling, not broker throughput, is the binding constraint for storage.
Data Path Implications
- Downsample or batch at the edge/gateway — sending pre-aggregated statistics (min/max/avg over a window) instead of every raw sample cuts message count by 10–100× before it ever reaches the broker.
- Use compact encodings (CBOR/Protobuf vs. verbose JSON) to reduce per-message bytes, directly lowering bandwidth and broker CPU for parsing/routing.
- Partition topics by device group/region, not a single global topic, so subscription filtering and fan-out cost scale with relevant traffic, not total fleet traffic.
Key Takeaways
- Naive single-broker, single-database architectures hit connection, throughput, or storage ceilings well below 1M-device scale; sizing must be checked quantitatively (
msg/s = N / interval), not assumed. - Thundering-herd reconnect storms after outages need jittered backoff and rate limiting, or a brief cluster restart can spike load far above steady state.
- Broker clustering, sharding, and geographic federation are the standard ways to scale connection count and throughput horizontally.
- Decoupling ingestion from processing via a message broker/queue gives backpressure absorption, independent consumer scaling, and fault isolation — the core reason brokers exist in IoT architectures.
- QoS level choice (at-most-once vs. at-least-once vs. exactly-once) directly trades reliability for broker/network cost; match it per traffic type (telemetry vs. commands).
- Edge-side downsampling, batching, and compact encodings reduce load before it reaches the broker, often more cheaply than adding broker capacity.
Learning
Sign in to track your progress.
Evidence
Public projects engineers linked to IoT Scalability: Millions of Devices, Message Brokers.
No engineer has linked a project to this topic yet. Built something that proves it? Add the project and tag it with iot-connectivity-iot-scalability-millions-of-devices-message-broker — it then shows here and on your public profile.
