Prompt
need to store and query embeddings with tenant permissions
Latest observation
To store and query embeddings with tenant permissions, the key requirement is to enforce multi-tenant isolation at the storage/query layer, not just in application code.
Recommended approach
1) Add tenant metadata to every embedding
Store each vector with at least:
tenant_iddocument_id/item_id- optional
user_id,group_id,visibility,created_at
This lets you filter results so a tenant only searches their own data.
2) Enforce access control before vector search
Before running similarity search:
- authenticate the caller
- determine allowed tenant(s)
- inject a mandatory filter like:
tenant_id = :current_tenant- or
tenant_id IN (:allowed_tenants)
Never rely on the client to send the tenant filter.
3) Use a vector database or database with metadata filtering
Good options:
- Postgres + pgvector: simple, strong security, easy tenant filtering with SQL/RLS
- Pinecone / Weaviate / Qdrant / Milvus: support payload/metadata filters
- Elasticsearch/OpenSearch kNN: also supports filters
Best pattern: row-level security + vector search
If you use Postgres + pgvector, you can combine:
- embeddings in a table
- tenant column
- Row Level Security (RLS) for hard isolation
Example table:
CREATE TABLE embeddings (
id BIGSERIAL PRIMARY KEY,
tenant_id UUID NOT NULL,
document_id UUID NOT NULL,
embedding vector(1536) NOT NULL,
content ტექxt,
created_at TIMESTAMP DEFAULT now()
);
Query:
SELECT id, document_id, content
FROM embeddings
WHERE tenant_id = $1
ORDER BY embedding <-> $2
LIMIT 10;
With RLS, even if a query is buggy, the DB still blocks unauthorized rows.
If you need per-user permissions, not just per-tenant
Add an ACL layer:
Option A: document ACL table
CREATE TABLE embedding_acl (
embedding_id BIGINT REFERENCES embeddings(id),
user_id UUID,
role TEXT, -- owner/viewer/editor
PRIMARY KEY (embedding_id, user_id)
);
Then filter with joins before vector ordering.
Option B: group-based access
Store:
tenant_idgroup_idvisibility
Then query only embeddings visible to the caller’s groups.
Important security rules
- Keep tenant_id server-controlled
- Use parameterized queries
- Apply filtering before or during vector ranking
- Don’t return raw embeddings to clients unless needed
- Log access for auditing
Example architecture
- User authenticates
- API gets
tenant_idand permissions from JWT/session - Query service searches embeddings with
tenant_idfilter - Results are ranked by similarity
- Optional post-filter by ACL if needed
If you want strict isolation
Best options, in order:
- Separate database/schema per tenant
- Shared DB + RLS
- Shared vector index + mandatory metadata filter
Separate DB/schema gives strongest isolation, but higher operational cost.
If you want, I can provide:
- a Postgres + pgvector schema
- a Qdrant/Weaviate/Pinecone design
- or a sample permission-aware search API in Python/Node/Go.