Skip to content

Tenant Isolation & Data Residency

Consystence is multi-tenant by construction: tenants share the same cloud codebase and Orleans cluster, but no tenant can read or touch another tenant’s operational data. This page describes the isolation boundaries — how membership is keyed, how a request’s subdomain binds it to one org, how tenant state is kept apart, and how every resource is authorised against the org that owns it — and where customer data physically lives.

A tenant is the routed, cell-hosted workspace this page’s boundaries protect. Each tenant is minted by the account control plane with a stable, immutable id (org_ followed by 32 hex digits), addressed by a human-readable slug under its own subdomain — {slug}.consystence.com for Enterprise tenants, {slug}.consystence.dev for Integrator tenants, trial tenants and individual sandboxes — and hosted on exactly one cell. It is distinct from an account-plane organisation: a free members-and-invites container with no slug, subdomain, or cell — creating an organisation does not create a tenant or an isolation boundary. A paid tenant is owned by an organisation; an organisation may also hold its one free trial (simulation) tenant; an individual’s sandbox tenant has no owning organisation at all. Within a cell, this page uses “org” for the tenant that owns a resource. A site is a path within a tenant (/sites/{code}), never a top-level domain. See the org and site model for the full hierarchy.

Membership in an org is the unit of access, and it resolves to exactly one of three roles — owner, admin, member — described in roles.

Identity comes from Entra External ID (CIAM). The stable membership key is the Entra oid — the object identifier that is constant for a user across sessions. Email is a verified attribute used for display and invitations; it is not identity, and it can change. The pairwise per-relying-party sub claim is not used as the membership key.

When a request arrives, the caller’s oid is checked against the membership directory for the org being addressed. Active members pass; pending or revoked members fail closed; non-members resolve to zero access. See authentication for how each kind of sign-in establishes the caller’s identity (a site-PIN sign-in carries no oid — it proves site presence, not org membership).

Three boundaries stack on top of each other. Each is independent — a request must clear all of them — so a defect in one does not silently open the tenant boundary.

flowchart TD
  A["Request to<br/>acme.consystence.com"] --> B["Subdomain boundary<br/>subdomain &rarr; org slug 'acme'<br/>caller oid validated vs org"]
  B --> C["Tenant-scoped state<br/>state keyed by org or site<br/>each site owned by one org"]
  C --> D["Resource-to-org authz<br/>derive owning org from resource id<br/>validate vs caller membership"]
  D --> E["Tenant-scoped resource"]

Every org is a distinct subdomain. At the request boundary, the server maps the subdomain to the org slug, validates the caller’s membership against that org, and rejects mismatches before any business logic runs. A user holding a valid token for one org cannot reach another simply by changing the host.

Tenant state is keyed by the org that owns it or by one of that org’s sites, and every site belongs to exactly one org: a site is registered to its owning org when it is created, and no other org can register the same site. Two tenants’ resources are therefore held separately, with no shared state. That site-to-org registration is also what lets the authorisation layer below resolve a site id back to its owning org.

Role checks answer who you are (are you an owner, admin or member of an org?). This layer answers a second question: which tenant owns the specific resource this request touches. A request can also name a resource directly by its identifier, so every such request is checked against the organisation that owns that resource, as described below.

Every caller-facing surface — an HTTP endpoint or a SignalR hub method — that reads or streams a tenant-scoped resource must, before touching the resource:

  1. Derive the resource’s owning org from the resource identifier. Resource ids are site-scoped; membership is org-scoped. The owning org comes from the site-to-org registration made when the site was created; an id registered to no org is denied.
  2. Validate that org against the caller through a single shared membership check, keyed by the caller’s Entra oid against the derived org (active members only). A failed check denies the request.

The invariant, in one sentence: the org validated is the org of the requested resource, derived from the resource id — never the caller’s session or home org, and never merely “has some org context.”

Cross-tenant isolation is enforced structurally in CI, not by review alone.

Consystence operations staff who administer the platform hold a platform role, separate from the organisation roles, that lets them reach a tenant’s resources for support, diagnostics and onboarding. It is the only access that crosses the tenant boundary.

Today, hosted platform data (tenant configuration, historian, operational records and the operational journal) is stored in Azure Australia East (Sydney). Data held by a site server stays on your infrastructure, except what you configure it to sync to your cloud tenant, and what it sends for AI inference (through the hosted advisory service or, where the server’s administrator has enabled a direct route in its settings, directly to a model provider). Identity, billing, Cloudflare’s global network (which carries requests to your tenant’s subdomain) and a few other services operate overseas; they are listed in the subprocessor register.

CategoryStored where
Tenant configurationAzure Australia East (PostgreSQL)
Historian samples, tags, events, lineage, registryAzure Australia East (PostgreSQL)
Auth tables (signing keys)Azure Australia East (PostgreSQL)
Operational journal (equipment commands, alarm acknowledgements, changes to members, roles and site configuration, assistant conversations)Azure Australia East (PostgreSQL), kept as a permanent record
Event logAzure Australia East (PostgreSQL)
Container imagesAzure Australia East (ACR)
BackupsKept in Australia.
Telemetry (traces, metrics)Azure Australia East (Application Insights)

Identity is the expected exception in kind: Entra External ID is a global Microsoft service, so user identity records live in Microsoft’s tenant store. The platform receives only the claims in the sign-in token (oid, email, name). It keeps your oid and email as your account record, keeps your memberships keyed by oid (with a display name and, optionally, a display email), and records the acting person in audit and operational-journal entries.

Hosted operational data is stored in Azure Australia East. Since 26 October 2026, advisory AI requests have been processed outside Australia, a temporary exception to our in-Australia inference rule; the processors and locations are listed at consystence.com/trust. This applies to requests a site server relays through the cloud too. Advisory AI can be left off for a site.

The AI gateway keeps hash-only audit records and does not store prompt or completion text, and prompts are not used to train models. The assistant conversation itself (each message, answer and notice) is recorded in your tenant’s operational journal and kept as a permanent record (see the table above and the Privacy Policy). On a site server, the conversation is recorded in that server’s own journal on your infrastructure; that journal is not copied to the hosted service.

No additional region is stood up speculatively — US, EU, or on-prem-only residency is added only on a signed customer ask, each with its own routing partition.

  • Roles — owner / admin / member, the membership that the resource-org gate validates against.
  • Cell topology — how tenants are provisioned into cells above the layered stack.
  • Authentication — the credentials a client sends, and how a signed-in caller’s oid is established.
  • Licensing — the organisation tier and SKU pools (install capacity); a licence condition degrades a server but never gates operator control writes.