Azure IoT platform at the edge
Designing an Azure IoT platform that processes several million device messages a day — Java Spring Boot microservices, device models, and event-driven processing with a hardened edge.
The problem
Connected appliances generate a firehose of telemetry. On a bad Saturday, the platform I worked on had to ingest messages from several thousand connected devices, model each physical appliance in the cloud, and process the stream event-driven — while the consumer app on top expected data with single-digit-second freshness. Two things had to be true at once: the ingestion path had to absorb bursts without dropping a message, and the runtime underneath it had to stay dependable in production.
The resolution was to treat the platform as a pipeline with three independently scalable stages — ingest, stream, process — each owned by a dedicated Azure service, glued together by code, and locked down behind a hardened edge.
The architecture
The design separated concerns cleanly:
- Ingestion — IoT Hub accepts device telemetry with per-device auth and device twin state.
- Streaming — Event Hubs buffers and fans out the event stream to multiple consumers.
- Processing — Azure Functions (serverless) and stream processing handle enrichment, alerting, and persistence.
- State — device models give each physical appliance a queryable cloud identity.
resource "azurerm_iothub" "platform" {
name = "iot-platform"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
sku = "S1"
endpoint {
name = "events-out"
type = "AzureEventHub"
connection_string = azurerm_eventhub_authorization_rule.send.primary_connection_string
}
route {
name = "telemetry"
source = "DeviceMessages"
endpoint_names = ["events-out"]
enabled = true
}
}
The device model is the contract between hardware and cloud. Every appliance type gets one, registered in the registry, and every telemetry message is validated against it before it reaches consumers:
{
"dtmi": "dtmi:vzug:washer;1",
"telemetry": [
{ "name": "cycleState", "schema": "string" },
{ "name": "powerW", "schema": "double" },
{ "name": "rpm", "schema": "integer" }
],
"properties": {
"firmwareVersion": { "schema": "string", "writable": false },
"remoteLock": { "schema": "boolean", "writable": true }
}
}
The runtime was AKS with Helm-deployed services, GitOps delivery, and autoscaling so the platform absorbed traffic spikes without human intervention. Autoscaling was event-driven rather than guessed — a KEDA ScaledObject tied consumer replicas to the queue backlog behind each Event Hub consumer group:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: telemetry-consumer
namespace: iot
spec:
scaleTargetRef:
name: telemetry-consumer
triggers:
- type: azure-eventhub
metadata:
eventHubName: telemetry
consumerGroup: platform
threshold: "64"
minReplicaCount: 2
maxReplicaCount: 20
Security hardening
Industrial and consumer device data deserves defense in depth:
- X.509/TLS certificate lifecycle for device authentication — including a PKI hierarchy so certificates could be issued, rotated, and revoked.
- VNet isolation and Private Link for all PaaS services so no control plane traveled over the public internet.
- RBAC scoped per service, plus managed identities for workload authentication.
- ACR security — geo-replicated registry, vulnerability scanning, and image trust policies for a secure container supply chain.
Results
The platform handled several million messages per day reliably. Chaos testing on the Kubernetes workloads and event pipelines gave us confidence the system degraded gracefully instead of failing loudly.
Lessons learned
- Device models pay off early. Modeling devices as stateful entities made dashboards and alerting trivial to build on top of.
- The edge is a security perimeter. Treat every device certificate like it is already compromised and design the blast radius around that.
- Streaming and serverless pair well. Event Hubs + Functions absorbed bursts without over-provisioning a fleet.
An IoT platform is a pipeline problem, not a "connect the devices" problem. Once you treat it as a data pipeline with security as a first-class citizen, the hard decisions get easier.