NEWVectors or files. Pick a path.Start →
    Data Infrastructure
    15 min read
    Updated 2026-07-27

    How Do You Isolate Tenants in a Vector Index?

    The three architectures for multi-tenant vector search (index per tenant, shared index with a tenant filter, and namespaces or partitions), what each costs, and the failure modes specific to each. Covers why a tenant filter is a correctness boundary rather than a performance knob, why post-filtering silently returns fewer results than you asked for, and why an unindexed tenant field can turn a working filter into an empty result set.

    Multi-Tenancy
    Vector Storage
    Architecture
    Retrieval
    Security

    The Short Answer



    There are three ways to isolate tenants in a vector index, and the choice is mostly about how much you trust every query path in your codebase.

    Index per tenant gives isolation by construction: a query physically cannot reach another tenant's vectors because their data is not in the index being searched. It is the only option where a forgotten filter is harmless. It also has the worst economics, because every index carries fixed overhead, and it stops being viable somewhere in the hundreds of tenants.

    One shared index with a tenant filter has the best economics and the sharpest edge. Isolation now depends on a filter being applied on every single read path. A missed filter is not a bug, it is a data breach.

    Namespaces or partitions sit in between: logical separation inside one deployment, where the engine scopes the query at the storage layer rather than trusting a filter you remembered to attach.

    Most teams should start with a shared index plus a filter, enforce the filter somewhere it cannot be forgotten, and move heavy or sensitive tenants to their own index as an exception rather than a default.

    Why This Is the First Architecture Question



    Anything you build for more than one customer hits this on day one, and it is expensive to change later because it determines your index layout, your cost model, and your blast radius during an incident. It is also easy to get subtly wrong in ways that only appear at scale or under a specific query shape, which is what the rest of this guide is about.

    Option 1: One Index Per Tenant



    Each tenant gets a physically separate index.

    What it buys. Isolation is structural. There is no query, however malformed, that returns another tenant's rows. Per-tenant operations become trivial: deleting a customer is dropping an index, re-embedding one customer does not touch anyone else, and you can put different tenants on different models or dimensions.

    What it costs. Fixed overhead per index is the problem. An HNSW graph carries per-index memory that does not shrink to zero just because a tenant has 400 documents, and most managed services bill a minimum per index or per cluster. A thousand tenants with a few hundred vectors each is pathological: you pay a thousand baselines to store a corpus that would fit comfortably in one index.

    When it is right. Few tenants, large per-tenant corpora, hard compliance boundaries, or per-tenant model differences.

    Option 2: One Shared Index, Filtered by Tenant



    Every vector carries a tenant identifier in its payload, and every query filters on it.

    What it buys. One index, one memory footprint, one set of operational work. Costs scale with total vectors rather than tenant count, which is why almost every product at scale ends up here.

    What it costs, and this is the part to take seriously. The filter becomes a correctness boundary. In the per-index design, forgetting the filter returns nothing unusual. Here, forgetting it returns *other customers' data*, ranked by relevance, in an interface you designed to look authoritative. That is a security incident with a very quiet failure signature: nobody gets an error, results simply look a little more diverse than they should.

    Treat it accordingly. The filter belongs in a layer that cannot be bypassed, a client wrapper, a service boundary, or a retriever definition that the application cannot issue queries around. If a developer can write a raw query against the index, you do not have tenant isolation, you have a convention.

    Option 3: Namespaces and Partitions



    Most engines expose a middle option: a namespace, partition or collection scope that the engine applies at the storage layer. The query names the scope and the engine restricts the search space, rather than the query naming a filter that the engine evaluates.

    The practical difference is where the guarantee lives. A payload filter is data that must be correct on write and matched on read. A namespace is addressing: you cannot accidentally read outside the one you opened. It also usually gives you cheaper per-tenant deletes and independent index maintenance without paying for a fully separate deployment.

    The Failure Modes Nobody Warns You About



    Post-filtering can return fewer results than you asked for



    If the engine retrieves the global top-k and then drops rows that fail the filter, a small tenant can get almost nothing back. Ask for 10 results, retrieve the 10 nearest vectors across all tenants, discard the 9 belonging to other tenants, return 1. The query succeeded. The relevance was fine. The answer is still wrong, and it gets worse as the tenant gets smaller relative to the corpus, which means it fails hardest for your newest customers.

    Pre-filtering (restricting the candidate set before the search) or filtered search inside the graph traversal avoids it. Filtered vector search: pre, post and in-place covers the mechanics and which engines do which.

    An unindexed tenant field turns a filter into an empty result set



    A filter on an unindexed payload field is a full scan. On a small corpus you will not notice. On a large one it can exceed the engine's stage or query timeout, and depending on the engine the query then comes back degraded or empty rather than slow, which reads like "there is no data for this tenant" instead of "this query was too expensive".

    This is not hypothetical. We hit exactly this shape in our own stack in July 2026: a filter on a user field was pushed down across three storage forms, only one was indexed, the other two full-scanned at roughly four seconds each, the sum crossed a five second stage ceiling, and the stage was cancelled and returned zero results while one leg had already matched 141,458 documents in two seconds. The data was present the whole time. Index the tenant field at provisioning time, not when someone reports a slow query.

    Deleting a tenant is slower than creating one



    In a shared index, "delete this customer" is a filtered delete over potentially millions of vectors, plus whatever compaction the engine needs to actually reclaim the space. This matters for deletion SLAs under GDPR-style obligations. Per-index and per-namespace designs turn the same operation into dropping an object.

    Noisy neighbours are real but usually second-order



    One tenant re-embedding their whole corpus competes for the same write path and cache as everyone else. This is usually a capacity problem rather than an architecture problem, and it is the weakest of the arguments for per-tenant indexes.

    Choosing



    Index per tenantShared index + filterNamespaces
    Isolation guaranteeStructuralDepends on every query pathScoped by the engine
    Cost at 1,000 small tenantsPoor, fixed overhead x1,000BestGood
    Cost at 10 huge tenantsFineFineFine
    Delete a tenantDrop the indexFiltered delete + compactionDrop the namespace
    Per-tenant model or dimensionYesNoUsually
    Blast radius of a code bugOne tenantEvery tenantOne namespace
    The honest default for most products: shared index, tenant filter enforced at a boundary the application cannot route around, tenant field indexed from day one, pre-filtering rather than post-filtering, and a documented path to move a tenant onto its own index when compliance or scale demands it.

    How Mixpeek Handles It



    Mixpeek is a multimodal data warehouse: token-level indexing and retrieval over object storage. Tenancy is a namespace, the option-3 shape above. A namespace scopes the vectors, the payload schema and the retrievers, so a query is issued against a namespace rather than issued globally with a filter you hope was attached.

    Two details that map onto the failure modes above. Payload indexes for user fields are provisioned when the namespace is created, through a single builder that every create, clone, quickstart and manifest path funnels through, so the unindexed-filter trap is closed at provisioning rather than left to be discovered. And access control is a separate layer (our open FGA implementation), so "which namespace" and "who may read it" are not the same decision.

    See namespaces for the scoping model and filters for narrowing within one. Pricing is per vector on MVS and per object on Managed, both from $25/mo, so namespace count is not itself a billing dimension.

    Related Reading



  1. Filtered vector search: pre, post and in-place for the filtering mechanics this guide depends on
  2. Multi-index search architecture when one tenant needs several indexes rather than the reverse
  3. Payload projection for agentic vector search for what else belongs in the payload alongside the tenant id
  4. Index freshness and incremental updates for keeping per-tenant data current
  5. Vector database cost comparison for the per-index overhead that decides option 1
  6. Best vector databases and best hybrid search engines for which engines support which isolation model
  7. Managed Mixpeek

    Put multimodal search to work

    Connect a bucket and Mixpeek runs the whole multimodal search pipeline for you: extraction, indexing, and search over your own objects. No models to wire up, nothing to host.

    Start with Managed
    MVS · bring your own

    Already have vectors?

    Keep your embeddings on your own cloud and run dense, sparse, and BM25 search directly on object storage. From $25/mo.

    Start with MVS

    Run this on your own data

    Point Mixpeek at the storage you already have and search your video, images, audio, and documents the way this guide describes. Build starts at $25/mo for up to 1M vectors.

    Search your own archiveRead Docs