Home / Filtering / Multi-Tenant Semantic Search: Isolation Patterns
ExplainerMulti-Tenant Semantic Search: Isolation Patterns
Multi-tenant semantic search is one search system that serves many customers, or tenants, while making sure each tenant’s queries only ever see that tenant’s own documents. There are three main ways to draw the boundary. A shared index with a tenant filter is the cheapest, but isolation depends on every query applying the filter correctly. A separate index, collection or cluster per tenant gives the strongest separation, but its overhead grows with every tenant. A shard per tenant inside one collection sits between them, and it is how Weaviate’s native multi-tenancy works. Weaviate stores each tenant on its own shard, so data in one tenant is not visible to another, and deleting a tenant deletes its data. Tenants can be set active, inactive or offloaded to cloud storage, so idle customers stop using memory.
Multi-tenant semantic search in four facts
- Tenant isolation means one customer’s queries can never return another customer’s data.
- A shared index with a tenant filter relies on application code adding the filter to every query.
- Weaviate multi-tenancy gives each tenant its own shard, and its documentation cites 50,000 or more active shards per node.
- Weaviate tenants can be ACTIVE, INACTIVE or OFFLOADED; only ACTIVE tenants accept reads and writes.
What is multi-tenant semantic search?
Multi-tenant semantic search is a search setup in which one system holds the documents of many separate customers and answers each customer’s queries from that customer’s documents only. A tenant is usually a company, a workspace or a single user.
A software company that adds AI search or a support assistant to its product faces the problem at once. Each customer uploads its own files, tickets or records, and each expects that nobody else can find them. Running one search system for all of them is cheaper and simpler than running one per customer. The challenge is keeping the separation reliable as the number of tenants grows from ten to a million.
“Multi-tenant” itself means one running instance serving many tenants, the standard model for software as a service. In semantic search it applies to the vector index, the keyword index and the stored objects together. The rest of semantic search stays the same: documents become embeddings, queries find near neighbours, and results can be filtered. What changes is where the walls go.
Why does tenant isolation matter for AI search?
Tenant isolation matters for AI search because a single missed boundary can show one customer’s private data to another, and AI features make that leak easier to trigger and harder to spot. A search result or a generated answer can quote any retrieved text.
With a classic search box, a leak shows up as a strange result in a list. With retrieval-augmented generation, the leaked passage may be summarised into an answer, with no visible sign of where it came from. An AI agent that runs searches on a user’s behalf widens the exposure further, because it issues queries nobody reviews. Personal data inside retrieved text adds legal risk on top of the trust problem.
Isolation also covers performance and lifecycle. One very large or very busy tenant should not slow everyone else down, the “noisy neighbour” problem. A customer who leaves should be removable completely, along with every vector and index entry. These three needs, data separation, fair performance and clean deletion, are how the isolation patterns compare.
What are the main tenant isolation patterns?
The main tenant isolation patterns are a shared index filtered by tenant, a shard per tenant inside one collection, and a separate index or cluster per tenant. They trade cost and simplicity against the strength of the wall.
In the shared pattern, every object carries a tenant ID property and every query adds a filter on it. In the shard-per-tenant pattern, the database keeps each tenant’s data in its own partition, and a query names the tenant instead of filtering. In the separate-index pattern, each tenant gets its own collection, database or even cluster.
The choice depends on tenant count, tenant size and how strict the separation must be. A few large enterprise customers with contractual requirements may justify separate deployments. Thousands or millions of small tenants make per-tenant indexes impractical. Many products mix patterns, for example a shard per tenant for most customers and a dedicated cluster for the largest.
When does a shared index with tenant filters work?
A shared index with tenant filters works when tenants are few or small, when isolation requirements are modest, and when every query passes through one code path that always adds the filter. It is the simplest pattern to start with.
Technically it is metadata filtering on one field. The vector search runs over the whole index but only returns objects whose tenant ID matches. How well that performs depends on pre-filtering versus post-filtering. Post-filtering can return too few results for a small tenant, because most of the nearest neighbours belong to other tenants. Pre-filtering and filtered ANN search avoid that, but a tenant that holds a tiny fraction of the index is a very selective filter, the case covered in filter selectivity.
The bigger weakness is human. Isolation is only as strong as the rule that every query includes the filter, and a forgotten filter in one new feature exposes every tenant. Deleting a tenant means finding and removing all its objects from a shared index. In a single shared index, keyword statistics such as BM25 document frequencies also span all tenants, so one tenant’s vocabulary can shift another’s scores.
How does a shard per tenant isolate data?
A shard per tenant isolates data by storing each tenant’s objects, vectors and indexes in a separate partition, so a query against one tenant never touches another tenant’s data. The database enforces the boundary instead of each query.
Each tenant’s shard has its own vector index and its own inverted index. A search for one tenant runs only over that tenant’s vectors, so a small tenant gets full results without selective filtering. Deleting the tenant removes the shard, which removes all of its objects in one operation. A crowded tenant’s index does not grow the search work of a small one.
Weaviate’s documentation says tenant shards are lightweight, citing 50,000 or more active shards per node, and roughly 20 nodes for a million concurrently active tenants. Tenants still share the node’s CPU, memory and disk, so a very heavy tenant can affect its neighbours. Deactivating idle tenants, replication and moving busy tenants are the tools for that.
How does Weaviate implement multi-tenancy?
Weaviate implements multi-tenancy as a collection setting that gives every tenant its own shard, with each read, write and query naming the tenant it targets. Multi-tenancy is off by default and must be enabled when the collection is created.
from weaviate.classes.config import Configure
from weaviate.classes.tenants import Tenant
docs = client.collections.create(
name="SupportDocs",
multi_tenancy_config=Configure.multi_tenancy(
enabled=True, auto_tenant_creation=True, auto_tenant_activation=True),
)
docs.tenants.create([Tenant(name="acme"), Tenant(name="globex")])
acme = docs.with_tenant("acme")
acme.data.insert({"title": "Refund policy", "body": "..."})
result = acme.query.near_text(query="how do refunds work", limit=5)
The enabled setting is immutable, so plan for multi-tenancy before the first import. Two optional settings help at scale. autoTenantCreation creates a tenant the first time an object is inserted for it. autoTenantActivation reactivates an inactive or offloaded tenant when a search, read, update or delete arrives. Both default to false and can be changed later.
Inside a tenant, everything else works as usual: vector, keyword and hybrid search, filters, and generative queries. A tenant can still use metadata filters for finer rules, such as a document’s department or language. Weaviate’s documentation describes this design as data isolation at a lower overhead than a collection per tenant.
How do tenant states reduce the cost of many tenants?
Tenant states reduce the cost of many tenants by letting idle tenants release memory or move to cheap cloud storage, while busy tenants stay loaded. In most products only a fraction of tenants are active at once.
Weaviate tenants can be ACTIVE, INACTIVE or OFFLOADED. Only active tenants accept reads and writes. Inactive tenants stay on local disk for fast activation. Offloaded tenants move to cloud storage through the offload-s3 module, and the documented target since version 1.26 is AWS S3. Two transient states, OFFLOADING and ONLOADING, appear while data moves. The older names HOT, COLD and FROZEN still work but are deprecated.
Weaviate’s guidance is to deactivate tenants not accessed for a while and offload those rarely accessed. State changes are eventually consistent across a multi-node cluster, so a reactivated tenant may take a moment to become available. Tenants using a flat index rather than HNSW use fewer hot resources, so the index type matters as well.
Is tenant isolation enough to secure AI search?
Tenant isolation is not enough on its own to secure AI search, because it separates customers but not the users and permissions inside each customer. It is one layer of several.
Within a tenant, an employee may see only some documents, by team, role or project. That needs per-document access control on top of tenant isolation, covered in permission-aware search. The tenant to query must also come from the authenticated session on the server, never from a value the user or an AI agent can choose. Otherwise a crafted request names another tenant and the isolation is bypassed.
Other layers sit around the search. Database authentication and role-based access control limit who can call which collection. Logs should record which tenant every query used, so isolation can be audited. Shared caches need the same care: a semantic cache keyed only on query similarity could return one tenant’s cached answer to another, as explained in what is semantic caching.
How should you choose a multi-tenancy pattern?
You should choose a multi-tenancy pattern by the number of tenants, the spread of their sizes and the strength of separation customers require. Most products land on a shard per tenant.
Use a shared index with filters for a prototype or a handful of internal teams. Use a shard per tenant for software with many customers, especially when most are small and many are idle. Use separate collections or clusters for a few large customers with strict contracts, data-residency rules or custom models. Changing patterns later means re-importing data, so the choice deserves thought early.
Whatever the pattern, test isolation directly. Create two tenants with overlapping content, query each, and confirm no result crosses the boundary. Searching vs filtering separates the ranking step from the restriction step, and bitmap filters and faceted semantic search show how filters run inside a tenant. Vector databases with metadata filtering compares filter support across products, and how to build semantic search covers the rest of the system.
Multi-tenant semantic search serves many customers from one system while keeping each customer’s data out of the others’ results. A shared index with a tenant filter is cheap but depends on every query applying the filter. A separate index per tenant is the strongest wall but grows costly. A shard per tenant, as in Weaviate’s multi-tenancy, isolates data, gives each tenant its own indexes and deletes cleanly. Tenant states let idle tenants go inactive or be offloaded. Add per-user permissions and server-side tenant selection, and test that no result ever crosses a tenant boundary.