REST and MQTT get compared as if choosing one excludes the other, but they're built for different communication patterns, and most functioning IoT platforms use both — REST for request/response interactions initiated by apps and services, MQTT (or a similar publish/subscribe protocol) for the continuous, asynchronous, many-device telemetry and command traffic that REST handles poorly at scale.
What each protocol is actually good at
| REST | MQTT | |
|---|---|---|
| Communication pattern | Request/response | Publish/subscribe |
| Connection model | Stateless, per-request | Persistent connection |
| Best for | App-initiated queries, config changes, one-off commands | Continuous telemetry, real-time updates, many-device fan-out |
| Overhead per message | Higher (HTTP headers, new connection or keep-alive) | Low (compact binary protocol, persistent connection) |
| Device power impact | Higher if used for frequent updates | Lower for frequent, small messages |
Why REST struggles for device telemetry at volume
REST's request/response, typically-stateless model works well when an app needs to ask a specific question and get a specific answer. It's a poor fit for a device reporting telemetry every few seconds across a fleet of thousands — the overhead of establishing (or even maintaining keep-alive) HTTP connections repeatedly, plus the header overhead of each request, adds up in both server load and, for battery-powered devices, unnecessary power draw compared to a lighter persistent-connection protocol.
Why MQTT fits device telemetry and command patterns
MQTT's publish/subscribe model matches how device fleets actually communicate: many devices publishing telemetry to topics, backend services subscribing to process it, and commands published to device-specific topics that individual devices subscribe to. A single persistent connection carries many small messages efficiently, with built-in quality-of-service levels that let the protocol handle at-least-once or exactly-once delivery guarantees without the application needing to build that reliability layer itself. This is why MQTT (or similar protocols like AMQP or CoAP for more constrained environments) dominates the telemetry and command-and-control layer of most IoT platforms.
A practical split that works for most platforms
- MQTT (or similar) for device-originated traffic — telemetry, status updates, and device-to-cloud events, where the device initiates and the pattern is continuous or event-driven
- MQTT for cloud-to-device commands that need to reach a device promptly while it's connected — configuration pushes, immediate action requests
- REST for app/service-facing APIs — the mobile app or web dashboard querying device state, triggering actions, managing users and fleets — where request/response semantics and standard HTTP tooling (auth, caching, rate limiting) are a better fit than pub/sub
In this split, MQTT handles the high-volume, device-side communication layer, while REST (or GraphQL, increasingly, for more complex query needs) handles the app-facing layer built on top of state that's been ingested from the device side — often the device shadow pattern discussed elsewhere bridges the two, giving REST APIs something stateful to query even though the underlying device communication is asynchronous.
When REST alone is genuinely sufficient
For products with infrequent device check-ins (periodic polling rather than continuous connectivity, common in some cellular/battery-constrained designs) and modest fleet size, a simpler REST-only architecture can be entirely adequate — the complexity of running and scaling an MQTT broker isn't automatically justified for every product. The decision should follow from the actual communication pattern and scale, not a default assumption that MQTT is required for any IoT platform.
How we approach this
We design the communication layer around the product's actual traffic pattern — device check-in frequency, fleet scale, and latency requirements — rather than defaulting to a particular protocol stack. See our cloud & device platform work for how this fits into a full platform build.
