On this page
- No other tenant's text was shown. Another tenant still changed the decision.
- Is a tenant_id filter enough for multi-tenant AI?
- The tenant is part of the identity, not a header
- Where do tenant boundaries leak in an AI application?
- Filter before you rank
- Caches, features and derived data need the tenant too
- Models and memory mustn't become a shared session
- Agents and tools can't broaden tenant authority
- Outputs and evidence are tenant data
- Can shared infrastructure be tenant-safe?
- Common anti-patterns
- Ten rules for end-to-end tenant isolation
- The result: shared infrastructure without shared meaning
- Frequently asked questions
- How Frozion keeps every action inside its tenant boundary
- Sources
Tenant isolation for AI means one tenant's data, state and authority can't be shown to, influence, or act for another tenant anywhere in the chain: retrieval and ranking, caches and features, model sessions and memory, tool calls, outputs and logs. A tenant filter on database queries protects one store, not the application.
No other tenant's text was shown. Another tenant still changed the decision.
A procurement application helps customers review software renewals. Each customer is a tenant. Every database query carries the tenant ID, and users can open only their own organization's contracts.
A user at Customer B asks whether a renewal has a termination penalty that should block automatic approval. The application searches a shared vector index. Each chunk carries tenant metadata, but the search takes the 20 nearest chunks across all tenants first and filters afterward.
Eighteen of the 20 belong to Customer A. They're removed before the prompt is built, so no Customer A text reaches the user or the model. Two Customer B chunks remain. The clause that mattered ranked 23rd across all tenants and first within Customer B. It never made the cut.
The model sees two harmless chunks, finds no penalty and recommends renewal. A procurement tool updates Customer B's case.
Every local control held: the query was filtered, the index removed foreign chunks, the model saw only Customer B text, the tool updated a Customer B record, and no alert fired. Customer A simply used up the retrieval budget and pushed out evidence Customer B was entitled to.
Is a tenant_id filter enough for multi-tenant AI?
No. A tenant filter on database queries protects one store. AI applications carry tenant data through indexes, caches, features, model sessions, tool calls, outputs and logs, and the boundary has to hold in every one.
"Every query includes the tenant ID" is still the right rule for the database. It just isn't the application boundary anymore. The same tenant shows up in a row, a file path, a vector chunk, a cache key, a feature, a chat session, a sub-workflow call, a tool argument, an export, a trace and a replay. Lose the tenant in any one of them and you can disclose data, decide on the wrong evidence, act on the wrong record, or show operational data to the wrong administrator.
The definition includes influence on purpose. AI applications don't just return records. They rank, summarize, infer, route and act, and another tenant's data can change all of that without appearing in the answer.
| Failure mode | What crosses the line | Example |
|---|---|---|
| Disclosure | Content becomes visible to another tenant | A cached summary is returned to a tenant with the same local document ID |
| Influence | Another tenant's data changes ranking, context or availability | Global top-k crowds out the right tenant's evidence |
| Action | A tool acts on another tenant's resource | A broad service credential updates the wrong customer's record |
| Evidence | Logs, traces or replay expose another tenant | A support engineer opens a trace with another tenant's prompt |
The tenant is part of the identity, not a header
A tenant ID shouldn't be an optional string copied from a request header. It's part of who is acting and which resource is being touched. Derive it from trusted identity and policy, never from a parameter the caller (or the agent) supplies.
Local identifiers make this urgent. Two tenants can both have document 7421 or case 17. Those numbers mean nothing alone. The real identity is tenant plus resource type plus local ID, and sometimes legal entity or region too. Carry that tenant scope with the work across every step that reads data, picks a model, calls a tool, emits an event, writes a cache or records evidence. Within a tenant, the same discipline applies to business domains; see taxonomy-scoped authorization.
Where do tenant boundaries leak in an AI application?
They leak wherever data is selected, derived, remembered, acted on or recorded: retrieval and ranking, caches and features, model sessions and memory, agent and tool calls, generated outputs, logs and replay, and shared capacity.
| Surface | Common failure | Control |
|---|---|---|
| Database and documents | Caller-supplied tenant ID; local IDs treated as global | Tenant from trusted identity; composite resource IDs; object-level checks |
| Files and storage | Paths, signed links and exports not tenant-bound | Tenant namespaces, short-lived links, named recipients |
| Vector and keyword search | Global candidates, late filtering, unlabeled chunks | Tenant filter before ranking; chunk-level labels |
| Features and caches | Tenant missing from the key or invalidation rule | Tenant in every key; tenant-aware invalidation |
| Model context and memory | Sessions, summaries or prompt caches reused across tenants | Separate sessions and memory; provider and retention by policy |
| Agents and sub-workflows | Child inherits broad parent access | Pass tenant scope explicitly; recheck at each step |
| Tools and APIs | Service credential accepted without checking ownership | Object-level check on every action; audience-bound credentials |
| Outputs | Reports, links or citations reach the wrong audience | Typed outputs, redaction, recipient checks |
| Logs and replay | Support views show other tenants' payloads | Tenant-scoped evidence and permission-aware inspection |
| Capacity | One tenant starves another's model calls or queues | Per-tenant budgets, quotas and concurrency limits |
Filter before you rank
Retrieval is the most important new tenant boundary, because it decides which information gets to influence the model at all. The control point isn't the final result set. It's candidate generation, filtering, ranking, reranking, chunking, summarization and context assembly.
OWASP's guidance on vector and embedding weaknesses points the same way: label chunks with access metadata, authorize at retrieval time, and don't rely on permissions captured at indexing. A sound retrieval path can answer:
- Which tenant scope governed candidate generation?
- Did any unauthorized item take part in search, reranking or summarization?
- Was the tenant filter applied before the top-k limit or diversity rule?
- Were query expansion, synonyms and reranker inputs drawn only from this tenant?
- Can you list every item that entered the context and every candidate excluded?
Shared indexes aren't unsafe in themselves. Separate indexes, tenant partitions and mandatory prefilters are all valid. What matters is that the choice is explicit.
Caches, features and derived data need the tenant too
Derived data is usually less protected than source data. A row has clear ownership; the embedding, feature, summary or cached response built from it often doesn't.
A cache key such as contract-summary:{document_id} is unsafe when document IDs are only unique within a tenant. A safer key includes the tenant, source revision and policy scope: contract-summary:{tenant_id}:{document_id}:{revision}:{scope}. The general rule is simple: anything whose contents or eligibility depend on the tenant either carries the tenant in its identity or lives in a store that enforces it.
Invalidation has to be tenant-aware as well. When a document's permissions change, a customer offboards or a legal entity moves, derived artifacts shouldn't stay reachable under the old assumptions. Provenance tells you which downstream artifacts came from the affected source and which decisions relied on them.
Models and memory mustn't become a shared session
The base model usually isn't the boundary. Everything around it is: prompts, retrieved context, tool descriptions, conversation history, working memory, prompt caches, provider-side retention and outputs. A shared model is fine when sessions, memory and caches are separated by tenant, context is assembled only from eligible sources, and provider, region and retention are chosen by policy.
Agents add a twist. Working memory can outlive one step, spawn child tasks or be written to long-term storage. Every memory item should be bound to tenant, purpose and retention, and a child agent can't broaden those just because it runs in the same process. Model choice is an isolation decision too: some tenants or data classes allow a public endpoint, others need a private deployment, a specific region or no provider retention.
Agents and tools can't broaden tenant authority
An agent can find a tool, build arguments and propose a plan. None of that proves the tool is allowed for this tenant or that the target record belongs to it. A broad service credential is the classic trap: the API authenticates the software and never checks that the object belongs to the tenant that started the work. That's broken object-level authorization, first on OWASP's API list for good reason.
Bind every consequential tool call to the tenant scope and delegated authority it runs under, the exact tenant-bound record, the allowed action and purpose, any approval, and a narrowly scoped credential meant for that one service. Event-driven workers should rebind the tenant when they resume rather than inferring it from a session variable. For how authority should narrow across hops, see AI agent identity and delegated authority.
Outputs and evidence are tenant data
Isolation often weakens after the answer is generated. The result lands in a shared cache, a file store, a notification, a webhook or a chat channel. Citations can reveal more than the prose. A generated link can point to an object the recipient can't otherwise reach. Check which tenant and record an output concerns, what shaped it, which fields may go to this recipient, where it may be stored and for how long.
Operational evidence deserves the same care, and often more. Traces, prompt captures, retrieval snapshots and tool payloads hold more than the user ever saw. A support engineer may investigate Customer B without being allowed to see Customer A. An auditor may need proof the boundary held without browsing the content. Logs and replay should be tenant-scoped, redacted by role and closed to cross-tenant inspection by default. The control that proves isolation mustn't become a leak itself.
Can shared infrastructure be tenant-safe?
Yes, when the isolation rules are explicit, enforced at every surface and tested. The danger isn't sharing; it's sharing with no clear owner of the tenant rules.
| Pattern | Strength | Condition |
|---|---|---|
| Dedicated resource per tenant | Simple to reason about | Lifecycle, cost and evidence still tenant-bound |
| Partitioned shared resource | Efficient with clear separation | Partition chosen from trusted tenant scope, not bypassable |
| Shared resource with mandatory filter | Flexible and efficient | Filter applies before data can influence ranking or output |
| Explicit cross-tenant service | Admin, aggregate analytics, migrations | Separate purpose, authority, minimization and record |
Then treat isolation as something you test continuously, not once. New caches, indexes, tools, mappings, model routes and support features reintroduce cross-tenant paths after the security review is done. A useful test set includes two tenants with identical local IDs, near-identical documents competing in shared search, cold and warm caches, permission revocation after indexing, offboarding, agents delegating across waits and retries, broad credentials reaching for another tenant's records, export and webhook paths, support and replay access, and noisy-neighbor load.
The invariant to test isn't "no foreign row returned." It's this: no other tenant's data, state, authority or artifact may influence or produce the output or the business effect.
Common anti-patterns
| Anti-pattern | Why it fails | What to do instead |
|---|---|---|
| "Every SQL query has tenant_id" | Search, caches, models, tools and logs stay unscoped | Hold tenant scope across every surface |
| Tenant from a request header | Untrusted input picks the security domain | Derive tenant from trusted identity and delegation |
| Filter after global top-k | Blocks disclosure but changes ranking and recall | Filter before ranking and budgets |
| Tenant only on the source document | Chunks, embeddings and summaries lose it | Label every derived artifact |
| Cache keyed by local ID | Two tenants collide or reuse a result | Put the tenant in the key and invalidation |
| One service credential for all tenants | Authenticates software, not ownership | Object-level checks on every call |
| Shared model memory | Earlier context shapes another tenant's answer | Separate sessions, memory and caches |
| Global support and replay views | Evidence becomes a disclosure path | Tenant-scoped, redacted inspection |
Ten rules for end-to-end tenant isolation
- Treat the tenant as part of identity and resource identity, never an optional parameter.
- Derive tenant scope from trusted identity, not caller or agent input.
- Carry tenant scope through data, retrieval, context, models, agents, events, tools, outputs and evidence.
- Stop unauthorized candidates from affecting retrieval or ranking, not just from appearing.
- Put the tenant in the identity of every derived artifact, cache entry, feature and memory item.
- Check object-level ownership at every consequential tool call, even with a valid credential.
- Choose model session, provider, region, retention and memory isolation by policy.
- Treat logs, traces, lineage, replay and support consoles as tenant data.
- Test disclosure, influence, action, evidence and noisy-neighbor cases with at least two hostile tenants.
- Record which tenant's data and authority shaped each outcome.
The result: shared infrastructure without shared meaning
Multi-tenancy is valuable because it lets you share infrastructure, logic and operations. AI doesn't change that. It multiplies the places where the tenant boundary has to survive. Search selects evidence, caches and features create derived facts, models keep context, agents delegate, tools act, outputs travel and logs keep the history. Each surface can be locally correct while the application loses track of the tenant between them.
Hold the tenant as part of identity, enforce it at every surface, test it against hostile tenants, and keep a record of which tenant shaped each outcome. A database filter protects a query. Tenant isolation protects the application.
Frequently asked questions
Is row-level security enough for a multi-tenant AI application?
It protects the primary database, which is necessary but not sufficient. Tenant data also lives in vector indexes, caches, features, model memory, tool calls, outputs and traces. Each of those needs the same tenant scope, enforced and tested on its own.
How do you isolate tenants in a shared vector database?
Apply the tenant filter before candidate generation and top-k, not after. Post-filtering can block disclosure while still letting another tenant's documents crowd out the right ones. Use separate indexes, partitions or mandatory prefilters, and label every chunk with its tenant.
What is cross-tenant influence?
It's when one tenant's data or workload changes another tenant's ranking, context, decision or service without any of its content being shown. A shared retrieval budget, a cache key without the tenant, or reused model memory can all cause it.
How does this work for agents we already run?
Route the agent's tool calls through a governed runtime over MCP or HTTPS. Each call runs under the delegated authority of the person the agent acts for, with record-level checks on the exact target, so a valid service credential is never enough to act on another tenant's data.
How Frozion keeps every action inside its tenant boundary
In Frozion, every agent has its own identity and, through Agent Delegation, acts with the authority of the person it serves and never more. Authorization combines roles, conditions, taxonomy scope, purpose and record-level checks on the exact target, so a valid system credential is never enough on its own. With Private & Hybrid AI, every task runs only where its data is allowed to go. Provenance & Evidence keeps one tamper-evident record per decision, with role views and scoped read-only auditor access.
Sources
- NIST SP 800-207, Zero Trust ArchitectureResource-centric authorization with no implicit trust.
- NIST SP 800-53 Rev. 5Access and information-flow enforcement, shared-resource protection, least privilege.
- NIST SP 800-210, General Access Control Guidance for Cloud SystemsMulti-tenant cloud access control and logical isolation.
- OWASP API1:2023 Broken Object Level AuthorizationAccess to a function doesn't grant access to every object.
- OWASP LLM08:2025 Vector and Embedding WeaknessesUnauthorized access and leakage in shared vector stores.
- OWASP Top 10 for Agentic Applications (2026)Memory and context risks for agents.
- RFC 8707, Resource Indicators for OAuth 2.0Bind a credential to the resource it's meant for.
- RFC 9068, JWT Profile for OAuth 2.0 Access TokensAudience validation for access tokens.
- NIST AI Risk Management FrameworkAI risk as a whole-system, lifecycle concern.
- W3C PROV-O: The PROV OntologyNeutral provenance relationships.
More in Governing AI agents
Identity & access 1
Tools & MCP 1
Other topics