Tenant isolation
How the boundary between organisations is enforced — and how it is proven.
Tenant isolation is the load-bearing security property. Everything else is defence in depth around it.
Three reinforcing mechanisms
Fail closed
The helper that resolves a tenant raises rather than returning a default. A blank tenant fails before any data is touched, so the worst case is an error, never an unscoped query.
Derived, never supplied
The tenant is always resolved server-side from the authenticated credential. It is never read from a request body, query string or header. There is no parameter a caller could set to claim a different tenant — the attack has no input to use.
Enforced by construction
Queries are built by canonical helpers that always emit the scope filter. Skipping the scope means not using the helper, which static analysis catches.
Per-store enforcement
| Store | Mechanism |
|---|---|
| Document database | Every read carries the tenant, plus the resource id for composite reads |
| Vector store | Mandatory tenant payload filter, added before the query runs |
| Graph | Tenant clause on every match, with parameterised queries throughout |
| Cache | Tenant-prefixed keys |
| Object store | Per-tenant bucket with a memory-scoped path prefix |
404, not 403
A read that crosses a tenant boundary returns 404, not 403.
403 would confirm the resource exists. Over enough requests that is an
enumeration oracle — an attacker learns your customer list one id at a time
without ever reading a record. Returning 404 denies the existence signal along
with the data.
Proof, not policy
The isolation rule is verified on every pull request: the test suite walks the abstract syntax tree of each endpoint and asserts that tenant scope is present, and an architecture linter enforces the layering rules in strict mode. A regression blocks the merge and the deployment pipeline.
This matters for a specific reason. "How do you know isolation is still intact after eighteen months of feature work?" is a question most vendors answer with a policy document. Here the answer is a failing build.
Logical against physical
Be precise about which you are getting:
| Deployment | Isolation |
|---|---|
| Shared | Logical — one set of engines, mandatory filters on every query |
| Dedicated | Physical — own engines in their own namespace, network-policed |
| Own infrastructure | Physical, and outside Chordian's estate entirely |
Logical isolation is enforced and verified, but it is enforced in software. If your threat model requires that a vendor bug cannot expose your data, the honest answer is a dedicated or own-infrastructure memory — not a stronger adjective applied to the shared tier.