Skip to main content

Keep tenant filters inside the retrieval query

2026-11-11 16:36:31.066192+00:00
Keep tenant filters inside the retrieval query

A tenant boundary belongs in the retrieval operation and in the authorization model that supplies it. Fetching a global top ten and hiding other tenants' rows afterwards can expose data to logging, reranking or model context before the interface filters it.

Use a synthetic corpus with tenant A and tenant B passages. Give B's passage wording that is deliberately closer to A's query. A request authenticated for A must never return B's passage, regardless of its similarity score.

A query shape can express the intended scope:

SELECT id, body
FROM passages
WHERE tenant_id = $1 AND active_revision = true
ORDER BY embedding <-> $2
LIMIT 5;

The parameters come from a trusted server context and a validated query embedding. This SQL excerpt assumes an existing pgvector schema; it has not been run against a database. The client must not choose an arbitrary tenant identifier that the server accepts without authorization.

Two tenant document groups behind separate query filters.

Test more than the final screen

Assert that excluded passage IDs never enter the candidate set, reranker input, answer prompt or cached result. Inspect error handling and debug traces as well. A UI that hides a title still leaks information if an earlier stage sends its full text to another service.

The pgvector filtering documentation explains vector queries with predicates and how approximate indexes can return fewer matches after filtering. Tune retrieval recall inside the permitted scope; increasing the global limit and filtering later is not a permission system.

PostgreSQL row security can provide another enforcement layer. Review the actual database role used by the application, since owners and privileged roles can bypass ordinary row policies.

Include revoked access

A document can change permissions after it was indexed. Retrieval must use current access rules or a reliably synchronized permission representation. A stale vector record carrying yesterday's tenant label can defeat an otherwise correct query.

Cache keys need the same authorization scope. If two tenants ask identical questions, a cache keyed only by question text can return one tenant's answer to the other. Re-check permission when opening a citation too; access to an answer does not authorize every linked source forever.

Test empty permitted results, a forged tenant parameter and a user removed from a workspace. Each case should have an explicit outcome without falling back to unrestricted search.

This design covers a retrieval boundary, not every form of data isolation. Storage exports, support tools, backups and administrative accounts require their own access review.