System design template

IoT telemetry platform architecture.

Assume every device is offline, on a bad network, running firmware from two years ago, and cannot be recalled. The architecture follows from that.

Download for macOS
v0.1.33 · .dmg · Apple Silicon & Intel
Signed & notarized by Apple · opens without a Gatekeeper warning
sha256 698955a0187bc039f4c74f5d05a9f10fbb27376a45788a0a241d1326b73873c7
Download for Windows instead
$curl -fsSL https://lucidtrain.com/install.sh | sh
IoT telemetry platform architecture. 12 components across 5 tiers.
IoT telemetry platform architecture. Rendered by the same ELK layout engine the app runs: the agent emits components, tiers and edges, and the engine places them, so the boxes cannot overlap.

The components

Every row below is read from the graph that produced the diagram above, so the two cannot disagree.

ComponentTierWhy it is there
DevicesClientIntermittent connectivity is the normal case
MQTT brokerEdgeLong-lived sessions, QoS 1 at least
Ingest gatewayEdgeSupporting component
Device identityApplicationPer-device certificates, revocable
DecoderApplicationBinary payloads to typed readings
Rules engineApplicationThresholds and alerts on the stream
Device shadowApplicationLast known state, readable while offline
OTA updatesApplicationStaged rollout, because a bad firmware bricks the fleet
KafkaDataSupporting component
Time series DBDataDownsampled by age
Cold storageDataSupporting component
GrafanaInfrastructureSupporting component

Design decisions worth arguing about

A diagram shows what was chosen. It does not show what it cost, and that is usually the part that matters in a review or an interview.

MQTT rather than HTTP

A persistent connection with small framing suits devices that are power-constrained and behind NAT, and it lets the platform push to them, which HTTP polling cannot do cheaply. The cost is a broker to operate, session state per device, and a connection count that becomes the platform's main scaling dimension rather than request rate.

Device shadows, because the device is usually unreachable

Applications need to read device state and set desired state at times when the device is asleep or out of coverage. A shadow holds last-reported and desired state so both work regardless, and the device reconciles on reconnect. The consequence is that every application is reading data that may be hours old, and the interface has to make that visible rather than pretending it is live.

Per-device credentials, individually revocable

A shared secret across a fleet means extracting it from one device compromises all of them, and rotating it means touching every device. Per-device certificates make revocation surgical. The cost is a provisioning process and a certificate lifecycle to manage across a fleet that may outlive the team that deployed it.

Staged firmware rollout, because a bad update is unrecoverable

Software you can roll back; firmware that bricks a device requires physical access. Rolling out to a small cohort, watching for devices that fail to check in, and only then continuing is the only real protection. It makes updates slow, which is the correct speed for an operation with no undo.

How it changes with scale

Ingest scales with device count times reporting frequency, and reporting frequency is usually the cheaper thing to change. Time series storage grows without bound unless downsampled, so retention tiers should be designed at the start: full resolution briefly, aggregates for a long time, raw archived to cold storage for the rare audit.

Where it breaks first

A reconnect storm after a network or broker outage. Every device attempts to reconnect at once, and each reconnect involves a handshake far more expensive than a telemetry message. Without jittered backoff in the firmware, and firmware is the part you cannot change quickly, the platform cannot recover under its own load.

Draw this yourself

Open the Diagram tab and describe the system. The agent emits a semantic graph rather than coordinates, so you can edit the components and the layout re-solves instead of drifting.

shell
$ Diagram an IoT telemetry platform: devices over MQTT, an ingest gateway with per-device certificate identity, a decoder turning binary payloads into typed readings, a rules engine for alerts, device shadows for offline state, staged OTA updates, Kafka, a time series database with downsampling, cold storage and Grafana.

When the shape is right, Implement in code turns the canvas into a markdown specification, every component, every relationship and the notes, and starts a real turn in the Code tab with it.

FAQ

Questions about this design

How do you handle devices with wildly different payloads?

A decoder layer keyed on device type, so the rest of the platform sees typed readings. Pushing format knowledge any further in means every consumer needs to know about every device generation forever.

Should telemetry be timestamped by the device or the server?

Both, recorded separately. Device clocks drift and devices buffer while offline, so the device time is what the reading means and the server time is when you learned it. Keeping only one makes late-arriving data impossible to interpret.

What time series database is appropriate?

Anything with downsampling and retention policies built in. The differentiator is rarely write throughput and almost always what happens to data as it ages, since that is what determines the bill.

How much processing should happen on the device?

As much as the power budget allows, because bytes sent are the expensive part on constrained networks. Sending an aggregate rather than raw samples is usually the single largest cost reduction available.

More templates