DeviceChain
English
Download
Open source, Apache-2.0, pre-1.0

Connect, detect and command.

Connect devices, store their telemetry, run rules and send commands on your own Kubernetes cluster. One install serves many tenants. DeviceChain has one edition. Its code is licensed under Apache-2.0.

A recorded run

See it run.

Rendered from a recording of a live run: 19 simulated quarry machines, each connected to DeviceChain as its own device. The figures on the cards were read back from the platform. A rule on the device profile raises the low-fuel alarm and sends the refuel command, and the truck reports that it completed it.
How it works

How a message is handled.

A device sends a message over MQTT, HTTP, Sparkplug B or LwM2M. After decoding the message and identifying the device, DeviceChain passes the event to services that store it, update the device's current state and evaluate your rules. Matching rules trigger actions. The services communicate over NATS JetStream.

Customers or business units can share an install, with tenant isolation in the database and on the message bus. The operator manages the install and its tenants. The multi-tenancy page explains the isolation.

Ingest

MQTT on the built-in NATS broker, HTTP POST, a Sparkplug B host application and an LwM2M server over CoAP/DTLS. The last two are optional services. The transport matrix lists what each transport supports in each direction.

Detect

Rules are typed conditions such as threshold, duration or absence. Each is written as a simple comparison or as a CEL (Common Expression Language) expression, and is evaluated against events as they arrive from the devices you choose.

React

A rule can raise an alarm, send the device a command, call a webhook, or publish to MQTT, Kafka, Amazon SNS or Amazon SQS.

Command

Device profiles declare commands and their parameters. DeviceChain stores each request and tracks its status, including delivery, the device's response and failures.

Device model

Typed, versioned device profiles.

Device types describe equipment such as meters, freezers or trucks. Each type uses a profile that defines its measurements, commands and detection rules. Several types can share a profile. You can edit a draft, publish a version or roll back to an earlier one.

Relate a device to its customer, site or asset, then use those relationships to find its readings. Typed relationships also let you describe connections between devices and other entities.

Device profiles
Metrics, typed command definitions and detection rules, published as versions.
Relationship graph
Typed, directed relationships between entities. Attributes can be declared as facets, so you can browse and filter by several at once, such as site, product line and owner.
Dynamic groups
A CEL expression over entity attributes. Membership is worked out with an indexed database query each time the group is read.
Customers, areas, assets
Devices are assigned to customers, areas and assets. Assets nest in a parent/child tree. Areas are named locations, and their boundaries are drawn as separate geofences. Each event records the device's tracked relationships as they stood when it was written, so history stays correct after a device is reassigned.
Credentials and replacement
A device keeps a stable token, and its credentials are separate and rotatable. Replacing failed hardware is one operation that retires the old unit's credentials and keeps the device's history.
Live state
The latest value of each measurement and whether the device is online. MQTT, Sparkplug B and LwM2M report connects and disconnects directly. An HTTP device counts as online while it keeps sending.
Rules

Test a rule against stored history.

Preview a draft against stored events to see when its condition would have fired. Preview uses the same rule compiler and engine as live processing.

Run preview from the automation canvas before publishing. It starts with empty rule state, does not load device attributes or apply group scope, and reports readings it skips or limits it reaches. The detection engine page lists its limits.

Three ways to write a rule
A form on the device profile, a visual automation canvas, or a plain-language description when the optional AI service is on.
Alarms
Alarms track active, acknowledged and cleared states, and can change severity. Clearing behavior depends on the rule; some windowed rules need new events before they can clear.
Eight kinds of rule
Threshold, rate of change, repetition, duration, absence, windowed aggregate, area correlation and connectivity. Absence and connectivity rules catch a device that goes quiet or disconnects.
Geofences
Draw them in the console or send polygons with holes over the API. A rule's condition can test containment with geo.inFence(...). Each location event carries the fence-set version in force when it arrived, so a replay uses the fences of its time.
Scope
Rules live on a device profile, and most kinds can be narrowed to a dynamic group. Group membership is recorded on each event when it arrives.
Authoring

Describe a rule in plain language.

With the optional AI service, type something like "raise a major alarm when a freezer stays above -15°C for ten minutes" and get a draft rule back. The draft goes through the same compiler as a hand-written rule. The service can use compiler errors to revise it, up to a fixed attempt limit. It returns a valid draft or the errors it could not resolve. Review the rule before publishing it; compilation checks its structure, not whether it matches your intent.

Published rules run without calling the model. To enable AI rule authoring, an operator registers the AI provider, makes a model available to the tenant and records the tenant's consent to external inference. Until all three are in place, the option is unavailable. You can leave the service off.

Dashboards

Versioned dashboards you can embed.

A dashboard belongs to a tenant and has drafts, published versions and rollback. You can build one against synthetic data before any device exists, then bind the same layout to a live fleet.

To show dashboards in your own React application, install the runtime packages from npm (@devicechain/widgets, @devicechain/dashboards and @devicechain/client). A standalone viewer gives users access to dashboards without the administration console.

Your data

Query your telemetry with SQL.

Telemetry is stored in TimescaleDB, a PostgreSQL extension. Query it directly with a PostgreSQL-compatible tool such as Metabase, Grafana, Power BI or psql, using a configured analytics read role.

Each tenant can be given its own read role, which sees an analytics schema of views over events, measurements, per-minute rollups, locations, alerts and connection changes. The database itself filters these views to the reader's tenant. Location access requires a separate grant. The SQL and BI guide covers the setup.

Read-only role
A login role for each tenant, with read access to the analytics views. You choose which tenants get a reader.
Or use the API
Applications use the GraphQL API, which reads the same tables the analytics views are built on.
Interfaces

GraphQL, client SDKs and MCP.

The API is GraphQL, with one schema for each area of the platform, and the schema files are published with the docs. Client SDKs are on npm for TypeScript (@devicechain/client) and on NuGet for .NET (DeviceChain.Sdk). The .NET SDK includes ahead-of-time compilation checks, and a Unity package, built from source, wraps it with Unity transports.

An optional Model Context Protocol server lets AI assistants such as Claude, Cursor or VS Code read devices, state, telemetry, alarms and commands. Calls use the signed-in user's token and permissions. The server exposes a selected set of read-only tools, not the full API.

GraphQL
One schema per platform area, with the schema files published.
SDKs
TypeScript on npm and C#/.NET on NuGet, plus the Unity package.
MCP
An OAuth 2.1 resource server with read-only tools, limited to the user's own tenant.
Run it yourself

Runs on Kubernetes, with PostgreSQL and NATS.

Entities are stored in PostgreSQL and telemetry in TimescaleDB. NATS JetStream carries the internal messaging, serves as the MQTT broker and holds key-value state. The install sets up both for you.

dcctl is a single binary that carries the Helm chart and the OpenTofu configuration. It drives docker, kubectl, helm and OpenTofu (or Terraform), which you install first, plus kind (Kubernetes in Docker) for a local cluster. dcctl install prepares a cluster and dcctl bootstrap creates an instance on it. Both commands can target a cluster you already have. The install and bootstrap workflows are tested end to end on kind, which also lets you run DeviceChain on a laptop. The repository also includes an OpenTofu configuration that creates a Google Kubernetes Engine cluster with separate database and service node pools.

On a Google Kubernetes Engine cluster of three 4-vCPU, 16 GB database nodes and three 4-vCPU, 8 GB service nodes, the v0.19.0 default HA install accepted 6,000 events a second for 10 minutes, twice. In those runs, event-by-event checks found no missing, duplicate or unexpected stored events. Each event carried one reading. The test used one tenant with its ingest ceiling raised for the test; at the default ceiling of 1,000 readings a second, one tenant's devices are admitted at most 5,000 a second. Service sizing documents the test conditions and resource settings. These results describe that workload and cluster, not a capacity guarantee.

The default cluster install also sets up Prometheus, Grafana and Alertmanager, with the platform's alert rules and dashboards. With backups enabled, both databases archive continuously for point-in-time restore. Restore and failover are tested with scripted drills on a running cluster, and the restore drill passes only if secrets stored before the backup still decrypt afterwards.

Also included

Operations and governance.

Alarm notifications, outbound delivery, audit, per-tenant limits, data retention and tenant deletion.

Notifications

Per-tenant policies route alarms by severity to email or webhooks, and escalate alarms nobody acknowledges. Escalation is safe to run on several replicas.

Outbound connectors

A separate service delivers rule actions to webhooks, MQTT, Kafka, Amazon SNS and Amazon SQS.

Egress boundary

Outbound connections block loopback, private, carrier-grade NAT, link-local and cloud metadata addresses by default. An operator can allow specific destination addresses or ranges for the instance.

Audit journal

The audit journal records changes to control-plane entities and who made them. Telemetry and derived state are excluded. When a tenant is deleted, its journal entries stay, with names and email addresses removed.

Governance

Per-tenant limits on ingest, outbound actions, AI requests and queued commands, which keep each tenant's load on a shared install within bounds you set.

Data lifecycle

TimescaleDB hypertables with compression, retention and continuous aggregates for per-minute rollups.

Tenant deletion

Deleting a tenant revokes sign-in at once and refuses new connections, ingest and commands within about a minute. It then erases the tenant's data from the database, telemetry store, broker, object store, key-value store and running rule engine, and records what each one did. Backups expire separately: by default, core data remains restorable for 30 days and telemetry for 7 days.

Secrets

Integration secrets are encrypted at rest, referenced by handle and write-only through the API.

White-labeling

Per-tenant branding that falls back to an operator default and then to the built-in look.

Device simulation

dcctl sim sets up a scenario, and the simulator, which you build from source, creates its customers, areas, assets and devices, then sends live telemetry over the same wire a real device uses.

Edge agent

Buffers to disk through a network outage (1 GiB by default, dropping the oldest events when full) and forwards when the link returns. When it replays its buffer, JSON events are stored once. Other payload formats can be stored twice.

Try it on a laptop.

The first-device quickstart takes about half an hour, including bootstrap. Bring up an instance on kind, create a device, send it a reading with curl and see the reading in the console.

DeviceChain is pre-1.0. It is a rebuild of the SiteWhere IoT platform. The simulator and Unity package are built from source; client SDKs are distributed separately. Read the release notes before upgrading: some pre-1.0 changes require a fresh install. APIs and database schemas can still change, and the notes list breaking changes first (see pre-1.0 stability). If something breaks, send us the steps and what you expected. Get in touch.