Multi-tenant RAG: keeping one customer's data out of another's answers
Engineering9 min read
Single-tenant RAG has an obvious worst case: a wrong answer. Multi-tenant RAG has a worse one — an answer built from another customer's documents, delivered to their competitor, with a citation.
That failure is not hypothetical; it is one missing WHERE clause. This is how we structure AskBrew so the missing clause is not possible, and the trade-offs of the alternatives.
Three isolation models
There are broadly three ways to keep tenants apart, in decreasing order of isolation and cost.
- A database per tenant — strongest isolation, and an operational burden that grows linearly with customers. Migrations become a fleet operation.
- A schema or namespace per tenant — middle ground. Cleaner than shared tables, but per-tenant index management and thousands of namespaces bring their own problems.
- Shared tables with a tenant column — one schema, one migration, one index. Isolation depends entirely on every query being correctly filtered, which is why it needs enforcement rather than discipline.
The dangerous path: service-role clients
A public widget endpoint has no logged-in user, so row-level security has no session to evaluate. These endpoints necessarily run with a service-role connection that bypasses RLS — which removes exactly the safety net described above.
This is the highest-risk code in a multi-tenant RAG product and it should be treated that way. The tenant must be resolved from the request's own credential — for us, the widget's public key maps to a workspace — and then every subsequent query scoped to that resolved ID explicitly.
It is worth marking those files clearly, keeping them few, and reviewing them differently from the rest of the codebase. Every query in them is load-bearing.
Isolation is not just the vector table
The chunks table gets the attention, but a leak from any adjacent table is the same incident.
- Conversations and messages — scope by tenant and by visitor, or one visitor's conversation ID lets them read or append to another's transcript
- Unanswered questions — these contain verbatim customer text
- Usage counters and billing state — cross-tenant reads here are a commercial leak rather than a personal one
- Tool configuration — endpoints and encrypted credentials belonging to one customer
- Cached embeddings or retrieval results, if you add a cache, keyed per tenant
One index, many tenants
A single HNSW index over all tenants' vectors with a tenant filter applied at query time performs well and avoids per-tenant index management entirely. New workspaces need no setup, which matters when they arrive continuously.
This is also a practical argument against IVFFlat in a multi-tenant product: its clustering wants representative data at build time, which sits awkwardly with a corpus that grows tenant by tenant. HNSW has no such dependency.
Test the boundary explicitly
Isolation is not something to verify by inspection. Write tests that would fail loudly if it broke.
- Seed two tenants with deliberately distinctive content, query one, assert nothing from the other appears
- Call the public endpoint with tenant A's key and tenant B's conversation ID; assert it is rejected
- Exercise the service-role paths in tests, not just the RLS-protected ones — the unprotected paths are the ones that matter
- Assert the retrieval function rejects a null tenant rather than defaulting to unscoped
Shared tables with row-level security, retrieval behind a tenant-scoped function, and a small well-marked set of service-role files is a structure where the dangerous mistake is hard to make by accident. That is a better property than a codebase where it is merely against convention.
Try it on your own content
Free to start — live in minutes.
Keep reading
Engineering
API-based AI support: integrating an assistant into your own product
When a hosted widget does not fit — custom interfaces, mobile apps, existing helpdesks — and what an integration needs to get right.
Comparison
AskBrew vs Chatbase: which fits your support team?
Both build a chatbot from your own content. They differ in what happens when the assistant is unsure, and in whether it can answer questions about a specific customer's account.
Buyer's guide
Chatbase alternatives: how to actually choose one
A buyer's guide to the AI support chatbot category — the four questions that separate these tools, and which type of alternative fits which situation.
Buyer's guide
Best AI customer support software: a buyer's guide for 2026
What AI support tools actually do, the three categories they fall into, and how to evaluate them without relying on vendor feature tables.
Engineering
Function calling for support bots
Letting an assistant look up a customer's order turns a content bot into something useful — and introduces an authorisation problem that must be solved outside the model.
Engineering
How to build an AI support agent
A build guide for the whole system: ingestion, retrieval, the answer gate, tool calls, and the operational pieces tutorials leave out.
Engineering
Preventing hallucinations in customer support bots
Grounding reduces fabrication but does not eliminate it. The techniques that actually work, and why an assistant that refuses is more valuable than one that always answers.
Engineering
pgvector vs Pinecone: choosing a vector store
A dedicated vector database and a Postgres extension solve the same problem differently. The deciding factor is usually not search performance.
Engineering
RAG architecture explained, for people shipping it
The components of a retrieval-augmented generation system, the decisions that actually affect answer quality, and where production implementations diverge from tutorials.
Engineering
How AI customer support actually works
What happens between a customer typing a question and an answer appearing: retrieval, grounding, confidence, and the decision to answer or hand over.