What you'll learn: how to serve several tenants from one assistant: a defensible isolation level, a tenant id from identity, a quota per tenant, a bill split from usage records, and a provable exit.
At a glance
Figure 1. One tenant id, set once from identity, travels to every step
How to read this: the tenant is read once from the verified token; every box below uses it, none takes it from the prompt.
- Pick the isolation level by what a leak would cost.
- The tenant id comes from identity and is enforced in code.
- A cap per tenant stops one taking all capacity.
- Tagged usage records split the bill.
Scenario
Composite scenario, not a real company. Lumen Industrial Supply, a fictional distributor, wants its Order and Policy Assistant to serve two regions, North and South, as separate tenants of one deployment; a sister company may join. Security asks what stops North reading South's data; Finance asks who pays. Numbers are illustrative.
What you will be able to do
- Choose and justify an isolation level.
- Name where the tenant id comes from and where it is enforced.
- Set per-tenant caps and split a shared bill.
Prerequisites
Latency, capacity and availability targets gives the 24-call ceiling; Identity and tenant isolation the token; security and threat modeling the threats.
Core ideas
Three isolation levels
Azure says you can share every resource or isolate every resource; the approaches between trade off "scale, isolation, cost efficiency, performance, implementation complexity, and manageability". It treats isolation as a spectrum; the three levels below are this lesson's cut of it.
Figure 2. Isolation levels (the levels and per-tenant keys are this lesson's design, not a source claim)
| Level | What is shared | What it protects | What it costs | Pick when |
|---|---|---|---|---|
| 1. Shared everything | Index, cache, service; a tenant id column separates rows | Only your code: a missed filter leaks | Lowest | Regions of one company |
| 2. Shared service, per-tenant data and keys | Service; own index, cache namespace and encryption key per tenant | A missing filter alone cannot cross an index | Moderate | Different companies |
| 3. Silo per tenant | Nothing | Highest, own load | Highest; Azure: 100 tenants "probably require 100 times" the cost | Contract or regulator demands it |
How to read this: each row down moves risk from code to budget.
Roughly, level 1 is Azure's fully multitenant model, level 2 its horizontally partitioned model and level 3 its automated single-tenant model.
Figure 3. Choosing a level
How to read this: the first yes decides the level.
Where the tenant comes from, and where it is enforced
AWS's SaaS whitepaper notes that an authenticated, authorised user can still reach another tenant's resources; isolation uses the tenant context "to limit access to resources". Read the tenant from the verified token and enforce it in five places:
| Place | Rule |
|---|---|
| Retrieval query | The filter is part of the query, not applied afterwards (RAG access control) |
| Every tool call | The tool server adds it; the model never supplies it |
| Cache key | Tenant, prompt version, normalised request (guardrails and caching) |
| Quota check | Counted per tenant before the model call |
| Logs and usage records | The tenant id is on every line |
Spot the flaw. A tool is defined as get_order(order_id, tenant_id) and the model fills in both arguments. What is wrong?
Answer
A prompt can steer the model into asking for another tenant's order. The tool server must set tenant_id from verified identity.