An Azure IoT Hub alternative is worth considering when your project needs true publish/subscribe between devices, apps and services rather than a device-to-cloud gateway. This article explains how IoT Hub's device-centric MQTT support differs from a full MQTT 3.1.1/5.0 broker, what to evaluate on each side, and a staged migration path to a standard broker that keeps your fleet running throughout.
What Azure IoT Hub Is Designed For
Azure IoT Hub is a managed service for connecting, managing and communicating with devices in Azure. Its strengths are fleet-oriented: a device identity registry, device twins, direct methods, cloud-to-device messages, and routing of telemetry into other Azure services. Devices can use MQTT, AMQP or HTTPS, with authentication by SAS token or X.509 certificate.
When you use MQTT with IoT Hub, you work within its device model. Devices publish telemetry to a device-specific topic such as devices/{device_id}/messages/events/ and receive messages on devices/{device_id}/messages/devicebound/#. Twin updates and direct methods have their own reserved topics. The service is the counterpart to every device, rather than a broker that relays messages between arbitrary clients.
That is a deliberate design for device management and cloud ingestion. It simply is not the same thing as a general-purpose MQTT broker. Microsoft also offers an MQTT broker capability in Azure Event Grid aimed at publish/subscribe scenarios, which is worth evaluating if you want to stay within Azure. Check Microsoft's current documentation for the exact capabilities of each service.
Device-Centric MQTT vs a Full MQTT Broker
| Aspect | Device-centric (IoT Hub style) | Full MQTT broker (e.g. ConnectMQ) |
|---|---|---|
| Topic namespace | Fixed, per-device reserved topics | Your own hierarchy, e.g. site/area/line/device |
| Device-to-device messaging | Through the cloud back end | Direct publish/subscribe between any clients |
| Wildcard subscriptions across devices | Not the model; back-end services read routed data | + and # across your topic tree |
| Browser and app clients | Usually via a back-end API | Secure WebSocket directly (8084, path /mqtt) |
| Retained messages and MQTT 5 features | Check current support | Retained messages, session expiry, topic alias, message expiry, response topic |
| Device management | Twins, direct methods, registry | Your own state topics and inventory |
| Cloud routing | Built-in routes to Azure services | External MQTT clients such as Node-RED or Telegraf |
The left column wins when device management and Azure integration matter most. The right column wins when you want standard MQTT semantics everywhere.
Signs a Full MQTT Broker Fits Better
- Dashboards and apps need live data directly. With a full broker, a browser app subscribes over Secure WebSocket without a back-end relay.
- Devices or machines talk to each other. A controller subscribing to a sensor's topic is natural in MQTT and awkward in a device-to-cloud model.
- You are building a Unified Namespace. An ISA-95 topic hierarchy needs a broker where you own the topic tree. See MQTT Sparkplug B and Unified Namespace.
- You want portable firmware. Standard topics and standard authentication make devices independent of any one cloud.
- Your systems span several clouds or on-premises sites.
Mapping IoT Hub Concepts to Standard MQTT
| IoT Hub concept | Standard MQTT equivalent |
|---|---|
| Device-to-cloud telemetry | Publish to site1/area1/line1/dev42/telemetry |
| Cloud-to-device message | Device subscribes to site1/area1/line1/dev42/cmd |
| Device twin reported properties | Retained message on .../dev42/state/reported |
| Device twin desired properties | Retained message on .../dev42/state/desired |
| Direct method | MQTT 5 request/response using response topic and correlation data |
| Connection state events | $SYS/broker/connection/{clientId}/state on ConnectMQ |
| Message routing | External subscriber, Node-RED flow or Telegraf agent |
MQTT 5's response topic is particularly useful for replacing direct methods: the caller publishes a request with a response topic, and the device publishes its answer there.
What You Take On When You Leave IoT Hub
A fair comparison includes the work that moves to your side. IoT Hub bundles a device registry, twin storage, method invocation and routing. With a plain broker you own those patterns:
- Device inventory. Keep a list of devices, their credentials and their firmware versions in your own system.
- State conventions. Agree on the shape of reported and desired state payloads, and document them so every firmware team follows the same rules.
- Command safety. Define who may publish to command topics and validate every command on the device before acting on it.
- Data routing. Run and monitor the subscribers or flows that move data to storage and analytics.
For many teams these are small, well-understood tasks. For others, especially those managing very large fleets with complex provisioning, the built-in device management of a platform is worth keeping. Decide with your own fleet size and team in mind.
Example: Device Code After Migration
Here is an ESP32 sketch using PubSubClient that publishes telemetry and listens for commands on topics you define, connecting to ConnectMQ over TLS:
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* MQTT_HOST = "broker.connectmq.com";
const int MQTT_PORT = 8883;
const char* MQTT_USER = "YOUR_USERNAME";
const char* MQTT_PASS = "YOUR_PASSWORD";
const char* CLIENT_ID = "YOUR_CLIENT_ID";
const char* TOPIC_TELEMETRY = "site1/area1/line1/dev42/telemetry";
const char* TOPIC_CMD = "site1/area1/line1/dev42/cmd";
WiFiClientSecure net;
PubSubClient mqtt(net);
void onMessage(char* topic, byte* payload, unsigned int length) {
String msg;
for (unsigned int i = 0; i < length; i++) msg += (char)payload[i];
Serial.printf("Command on %s: %s\n", topic, msg.c_str());
}
void connectMqtt() {
while (!mqtt.connected()) {
Serial.print("Connecting to MQTT... ");
if (mqtt.connect(CLIENT_ID, MQTT_USER, MQTT_PASS)) {
Serial.println("connected");
mqtt.subscribe(TOPIC_CMD, 1);
} else {
Serial.printf("failed, state=%d\n", mqtt.state());
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
// For production, pin the ISRG Root X1 CA with net.setCACert(...)
net.setInsecure();
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setCallback(onMessage);
}
void loop() {
if (!mqtt.connected()) connectMqtt();
mqtt.loop();
static unsigned long last = 0;
if (millis() - last > 10000) {
last = millis();
char payload[64];
snprintf(payload, sizeof(payload), "{\"temp\":%.1f}", 20.0 + random(0, 50) / 10.0);
mqtt.publish(TOPIC_TELEMETRY, payload);
}
}
setInsecure() is only for a first test. In production, load the Let's Encrypt root certificate with setCACert() so the device verifies the broker. The ESP32 MQTT tutorial covers certificate handling in detail.
A Staged Migration Path
- Design the topic tree. Decide on a hierarchy such as enterprise/site/area/line/device and separate telemetry, state and command topics.
- Bridge existing data. Run a small service that reads from your current IoT Hub consumers (for example the built-in event endpoint) and republishes to the new broker's topics. New dashboards can use the broker immediately.
- Replace routes. Recreate each Azure route as an external subscriber, Node-RED flow or Telegraf output that writes to the same destination.
- Move a pilot group. Update firmware or gateway configuration for a handful of devices. Check reconnect behaviour and plan limits; on ConnectMQ, MQTT 5 clients receive reason code 0x97 if a quota is exceeded.
- Roll out in waves and keep the previous configuration ready until each wave is stable.
Troubleshooting After the Switch
- Device connects, then disconnects every few seconds. Two devices share one client ID. Give every device its own credentials and client ID.
- Back-end service sees no data. Check the subscription filter. A filter of
site1/+/telemetrywill not matchsite1/area1/line1/dev42/telemetry; usesite1/#or the correct number of+levels. - Commands arrive twice. With QoS 1, duplicates are possible by design. Include a command ID and ignore repeats. The MQTT QoS levels guide explains why.
- Old state shows after restart. Retained messages persist until replaced or cleared. Publish an empty retained payload to clear one.
Try a Full MQTT Broker
You can explore the publish/subscribe model before changing any device. Create a free Serverless broker with no credit card, connect a test device and a browser client, and watch messages in the live topic explorer. For broader context, read the MQTT broker in the cloud guide, compare with the AWS IoT Core alternative article, and review what an MQTT broker does. Learn more at connectmq.com.
Frequently Asked Questions
Is Azure IoT Hub an MQTT broker?
IoT Hub supports MQTT for device communication, but within a device-to-cloud model with reserved topics. It is not designed as a general publish/subscribe broker between arbitrary clients.
How do I replace device twins with standard MQTT?
Use retained messages on reported and desired state topics. New subscribers immediately receive the last known state.
Can I keep using Azure services after moving to another broker?
Yes. An external subscriber or Node-RED flow can forward data from the broker to any Azure service through its normal APIs.
Where do I check current IoT Hub MQTT capabilities?
Use Microsoft's official Azure IoT Hub documentation, which describes supported MQTT features and limits for the current version.



