Skip to content

Architecture Overview

Consystence is an industrial operations platform for monitoring and operating plant equipment. This page is the map: the compute tiers data flows through, the control plane that provisions tenants, the Orleans grain runtime that holds state, and the server-driven UI that renders to multiple clients from one semantic tree.

Two ideas underpin everything that follows:

  • One codebase, two published artifacts. The same server code is published as two artifact identities — a multi-tenant cloud server that runs on a cell and hosts tenants’ workspaces and fleet views (Cloud) and an on-premises, single-organisation site server bound to live equipment (Site). The mode is stamped in at publish time, not selected by runtime configuration. It changes where signals come from and which endpoints are exposed — not the rendering, the grain model, or the wire protocol.
  • The server owns state and rendering. Clients are thin. State lives in Orleans virtual-actor grains on the server; the UI is rendered server-side and pushed to the browser as incremental patches.

Plant data flows from physical equipment up to a user’s client through the layers below: the Consystence server, the edge runtime (optional), the controllers and the field devices. Above them sits the account control plane, which provisions tenant organisations into self-contained cells.

flowchart TB
  CP["Account control plane<br/>account.consystence.com · id.consystence.com"]
  B["Client surface<br/>browser · csy CLI · WinUI3 (roadmap)"]
  subgraph Cell["A cell (hosted)"]
    SC["Consystence Server<br/>Cloud artifact"]
  end
  subgraph Plant["Customer plant"]
    direction TB
    SS["Consystence Server<br/>Site artifact"]
    E["Edge runtime<br/>(optional)"]
    C["Controllers<br/>ControlLogix · PLCnext"]
    F["Field devices"]
    SS <-->|gRPC| E
    E -->|reads| C
    SS -.->|"direct ControlLogix reads (early access)"| C
    C <--> F
  end
  B <--> SC
  B <--> SS
  CP -. provisions tenant orgs .-> Cell

ASP.NET Core 10, Orleans, and SignalR. This is the organisation runtime. As the Cloud artifact it hosts many tenants on a cell and serves fleet-level views from a replicated historian, and the account control plane provisions tenants onto it; as the Site artifact it is a single-organisation, on-premises server holding live equipment state. The browser connects here over SignalR; edge devices connect to a site server over gRPC.

A tenant lives on its own subdomain — {slug}.consystence.com for Enterprise tenants, {slug}.consystence.dev for Integrator tenants, trials and sandboxes; a site is a path under that subdomain (/sites/{code}), never its own domain. See the organisation and site model.

A .NET 10, single-silo Orleans runtime that runs at the plant, between a site server and its controllers. The Phoenix Contact PLCnext VL3 is a target platform for it. In our workshop we are proving the edge runtime for the VL3 on a Linux container, and a workshop edge also runs on an Nvidia Jetson Orin. The edge does store-and-forward (a local SQLite buffer) so it tolerates intermittent links, and streams to the site server over gRPC on HTTP/2 (TCP). Deploy the edge on segmented plant networks; in the border-gateway topology below, the PLCnext’s own port separation is the field-network boundary. See the edge runtime for detail.

Controllers are read by the site server (ControlLogix, early access) or through an optional edge, which speaks EtherNet/IP CIP to a Rockwell ControlLogix and gRPC (GDS) to a Phoenix Contact PLCnext. The site server reads a ControlLogix directly, read-only, without an edge. This is in early access: our engineers enable it per controller, and it has run at a site trial since 28 October 2026. Off by default. A PLCnext is read through an edge. Modbus TCP and OPC UA runtime drivers are roadmap. No broker SCADA sits in the data path, and production control stays on the plant’s existing control system. Consystence uses the vendor-neutral term controller (ControlLogix and PLCnext today) rather than “PLC”.

Where Consystence manages the control equipment, the accepted target topology puts a PLCnext border gateway between the isolated field network and everything above it; it has been demonstrated in our workshop. The gateway runs the deterministic control logic and speaks CIP / EtherNet-IP to field devices on an internal OT network, and the edge reads the gateway’s Global Data Space (GDS) process variables over gRPC — on a local Unix domain socket when the edge is co-located with the PLCnext, over TCP otherwise. See the PLCnext border gateway.

Variable-frequency drives, IO racks, sensors, and protection relays, connected to the controllers. The engineering model is controller → module → channel → tag/register; see core concepts.

Above the cells sits the account control plane, reachable at account.consystence.com, with identity provided by the Entra External ID (CIAM) tenant at id.consystence.com. It is a thin directory, router, and signup front door: it provisions tenant organisations into cells and resolves which cell a tenant lives on. It holds each organisation’s roster and each tenant’s owner and admin roles, which the cell mirrors; the rest of a tenant’s membership, its configuration and its state live inside the cell.

A cell is a fully self-contained deployment: its own Orleans cluster, its own PostgreSQL, its own historian, bound to a set of tenants. You scale the platform by adding cells, not by growing one cluster. A tenant never spans a cell, and the cell host itself is never surfaced to users — customers only ever see their tenant’s own subdomain. Each cell validates Entra/CIAM tokens directly, so the control plane stays out of the request and authentication path.

Cells, their invariants and how a tenant is provisioned onto one are covered in cell topology.

All stateful server objects are Orleans grains (virtual actors). A grain is a single-threaded, addressable object that Orleans activates on demand and places transparently across the cluster; the application never manages activation, locking, or placement. State is held in virtual actors keyed by the organisation/site hierarchy, which is also the tenant-isolation boundary. A connected client’s session state and a commissioned device’s runtime state are each held in their own grains; commands and other operational actions are recorded in an append-only operational journal in PostgreSQL. Platform services that are not stateful — authentication and the admin surface — are plain ASP.NET Core, not Orleans.

A design property worth calling out: the server’s batch pipeline is designed so that grain activation scales with infrastructure (controllers, devices, sessions), not with tag count, and so that each device is evaluated once per batch of tag updates rather than once per tag. It runs only where a deployment enables it (see scaling pipeline).

Consystence does not ship a single-page-application framework. The server builds a semantic UI tree — a renderer-agnostic tree of primitives (View, Card, Stack, StateBadge, Gauge, Button, Table, …) describing what a surface expresses, not how it paints. That tree reaches clients as a JSON wire format over the /hubs/ui-wire SignalR hub:

  • Browser — the browser wire renderer is the browser surface: it consumes the wire format (initial render, incremental patches, and client actions) on /hubs/ui-wire and renders the server-resolved tree as DOM. The earlier server-rendered HTML path has been retired.
  • CLI — the csy command-line client (csy ui), the first shipped consumer of the wire format, rendering the same tree in the terminal over the same hub.
  • WinUI3 — a native Windows renderer for control rooms and engineer workstations (roadmap; it will consume the wire format like the CLI and browser).

What stays invariant across renderers is the semantic tree, not any one client. New renderers consume the same wire protocol rather than growing private ones — which is what lets every surface be composed entirely server-side, with no privileged client.

The platform uses AI to answer questions about plant state and explain behaviour, grounded in live tags, alarms and history. It may propose an action; an operator reviews it and executes any command through the normal control path. Classifying alarms and events is on the roadmap.

The advisory plane is tiered: a cloud ladder with two rungs — a non-apex tier and an apex reasoning tier. A site-local model is roadmap. The cloud tiers are served by stateless, per-region advisory gateways. Since 26 October 2026, advisory AI requests have been processed outside Australia, a temporary exception to our in-Australia inference rule (see Trust and Inference location and residency). A site server relays cloud-tier calls through the cloud cell, where per-tenant usage is metered and model access is entitlement-gated. Whichever tier answers, it grounds its response in tenant data through a read-only data seam only — it holds no path to the control-write surface, so the advisory plane is structurally incapable of a control write. See AI architecture for the full picture.

A client sends one of three credentials: an Entra-issued CIAM Bearer token for people, a tenant API key (csk_ prefix, read-only by default) for scripts and integrations, or, on a site server only, an offline-capable site-PIN sign-in. There is no email/password login in Consystence itself — credentials are Entra’s responsibility. The stable membership identity is the Entra oid, not email. Organisation membership has exactly three roles: owner, admin, member — and site-level operational roles are a separate plane: on a site server, site functions are authorised by the user’s site role, not their organisation role. See authentication and roles.

Commercial entitlement is a separate concern — an organisation tier (free by default, or a paid Integrator or Enterprise tier arranged with our team) plus counted per-seat SKU pools for installs — and is designed to degrade rather than kill on expiry, never gating operator control writes. See licensing.