← All posts

Azure IoT Hub at Scale: Message Routing Without the Spaghetti

At 10,000 devices you can read every message. At 10 million you can't — you route. Here's the routing pattern that stays sane past a billion messages a day.

Azure IoT Hub starts feeling small around the time your fleet crosses ten thousand active devices. Not because the hub itself can't handle it — it scales to millions — but because the consumer side becomes a mess. One consumer trying to handle telemetry, twin-change events, lifecycle events, and command acknowledgements turns into a stateful monster.

The pattern: route by message type, fan out by purpose

Use IoT Hub message routing to split traffic at the source. Each route has a query (e.g. $body.temperature > 70, $twin.tags.tier = 'gold', or messageType = 'lifecycleEvents') and a destination endpoint:

  • Hot path — anomalies, alerts. Route to Event Hubs → Stream Analytics or Functions.
  • Warm path — dashboards. Route to Event Hubs → ASA → Cosmos DB / ADX.
  • Cold path — archival, ML training. Route to Blob Storage with auto-partitioning by date.
  • Twin events — desired-state sync. Route to Service Bus queues for ordered handling.
  • Lifecycle events — device created/deleted. Route to Event Grid → fan out to provisioning workflows.

Why this beats "one consumer reads everything"

  1. Scale independently. Hot path can have 32 partitions; cold path needs none.
  2. Different SLAs per path. Anomaly detection at ms latency; archival can be batch.
  3. Failure isolation. A broken alerting Function doesn't back-pressure your archival pipe.
  4. Auditing is free. Every route logs its own metrics in Azure Monitor.

The capacity math

IoT Hub Standard S1 = 400k messages/day per unit. Sounds like a lot until you realize a 10k-device fleet sending every 5 seconds is 172.8 million messages/day. You'd need 432 S1 units — absurd.

Switch to S2 (6M msgs/day/unit) or S3 (300M msgs/day/unit) before the bill becomes a meeting.

One thing the docs don't shout

Routing is exclusive by default — a message goes to the first matching route. To send the same message to multiple destinations, set fallback route behavior or duplicate-route the message and let downstream dedupe. Most teams discover this only when their analytics dashboard goes blank because they added an alerting route above it.

Chat with my AI