Architecture at a glance
This page is the short version. It shows the path an event takes from a device to a dashboard, an alarm and a command back to the device. Architecture is the long version: it describes every component, the data and messaging backbone, the deployment model and the secret store.
The shape of it
- Devices reach the platform through an ingest service. The platform's broker is the MQTT server
built into NATS.
event-sourcestakes MQTT and HTTP,sparkplug-ingestandlwm2m-ingestare opt-in services for those protocols, and a LoRaWAN network server posts to an inbound integration. - Every event is resolved once, near the front.
device-managementidentifies the device and attaches its context to the event, so everything downstream reads a self-describing event and needs no join. - Three consumers read the resolved events independently.
event-managementstores them,device-statekeeps the last known state of each device, andevent-processingevaluates rules. A slow consumer does not slow the others, because NATS JetStream sits between them. - Reactions go through the services that own the thing being changed. An alarm is an object in
device-management, a command is a record incommand-delivery, and an outbound call is delivered byoutbound-connectors, in its own process. - People and tools read through GraphQL. The console, the dashboards, your own code and the optional MCP server all use the same per-service GraphQL APIs under the caller's own token.
- One instance serves many tenants. Subjects on the bus and rows in the database carry the tenant; see Multi-Tenancy.
How a message flows
Follow one reading, a fuel level, from a device to a dashboard, then see what a rule does with it.
- The device publishes. It connects to the platform broker with its credential and publishes a
JSON event to its own topic,
{instance}/{tenant}/devices/{token}/events. The broker lets it publish to that topic and no other. See Connecting a Device. - Ingest decodes it.
event-sourcestakes the message, checks that the device in the body is the device in the topic, applies the tenant's ingest rate limit, and publishes the decoded event onto the pipeline. A message it cannot decode goes to afailed-decodestream instead. - The event is resolved.
device-managementauthenticates the device and looks up its device type and profile, and its assignments and tracked relationships, to customer, area and asset. It writes those onto the event as index dimensions and publishes the resolved event. - The event is stored.
event-managementwrites it to TimescaleDB, in batches, partitioned by tenant. Lifecycle policies (compression, retention, rollups) run there. - Live state updates.
device-stateconsumes the same resolved event and updates the device's current value for that measurement, stamped with the unit and type from its profile. - A dashboard updates. A dashboard widget has a GraphQL subscription open against the services
that hold the data.
event-managementpushes the new reading over its WebSocket bridge, and the widget redraws. See Dashboards. - A rule evaluates it.
event-processingconsumes the same resolved event and runs it through its detection rules. When the fuel level falls below a threshold, the rule fires on the rising edge. See Event Processing & Alarms. - The firing acts. The rule's actions run. One raises an alarm in
device-management, an object with a lifecycle that clears itself on the falling edge. Another enqueues a command. Others can hand a payload tooutbound-connectors, which delivers it to a webhook, a broker or a cloud queue. - A person hears about it.
notification-managementroutes the alarm to email or a webhook, according to the tenant's policy, and can re-notify while it stays unacknowledged. - The command makes the round trip.
command-deliverypersists the command, checks that the device is present, and publishes it to the device's own command topic. The device acts and publishes its result to its own command-response topic, andcommand-deliveryrecords the outcome. The command then ends as a success, a rejection by the device, or one of the states that say it never arrived; see Commands. If the device was away, the command was held until it returned.
The steps run on separate services connected by NATS JetStream, so each one can be scaled and restarted on its own. Observability describes the metrics and alerts that show where an event is held up.
Where to go next
- Architecture for every component and how the platform is deployed.
- Domain Model for devices, profiles, relationships and events.
- Transport Capability Matrix for what each way of connecting does in each direction.
- Measured throughput for what has been measured, on which workload and cluster.