The vector store is the newest sink in your platform, but the decisions that hurt later are old ones: which engine, what schema, how tenants are isolated.
Tier: Foundation · Workflow area: RAG data pipelines
Teams that "just add a collection" discover at month three that they cannot filter by department, cannot delete a customer's data cleanly, and cannot tell which embedding model produced which vector. This playbook walks the selection framework and a metadata schema that keeps every later playbook — sync, tuning, ACLs, observability — possible without a re-index.
Run the engine decision framework — in order, first match wins.
Write the choice down with the two rules that fired. Expected output: a one-paragraph decision record, not a 40-page bake-off.
Design the metadata schema before the first upsert. Minimum viable schema for any engine:
-- pgvector (local-first reference implementation)
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE rag_chunks (
chunk_id TEXT PRIMARY KEY, -- deterministic: sha256(doc_id + idx + content_hash)
doc_id TEXT NOT NULL,
tenant_id TEXT NOT NULL, -- tenancy from day one, even with one tenant
acl_tags TEXT[] NOT NULL DEFAULT '{}',
source_uri TEXT,
content TEXT NOT NULL,
content_hash TEXT NOT NULL,
model_version TEXT NOT NULL, -- which embedding model produced this vector
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
embedding vector(1024)
);
CREATE INDEX ON rag_chunks (tenant_id, doc_id);
Every field earns its place: doc_id enables delete propagation (pb-36), tenant_id and acl_tags enable isolation and ACL filtering (pb-38), content_hash enables incremental sync, model_version enables safe model migrations (pb-30). In Qdrant/Pinecone these become payload/metadata fields with the same names.
Pick the tenancy pattern deliberately. Three patterns, in rising isolation and cost:
tenant_id field, filter every query): cheapest, fine for internal teams; isolation is only as strong as query discipline — enforce it in a shared retrieval function, never in each caller.For pgvector, metadata filter plus row-level security gives filter-pattern economics with enforced isolation.
Prove tenancy with a leakage test, not a diagram. Seed two tenants with distinctive documents, query tenant A for tenant B's content. The metric that proves this step worked: cross-tenant leakage = 0 results over a 50-query adversarial set (paraphrases of tenant B's content asked as tenant A). Any nonzero result fails the design.
res = search(query="B's secret pricing table", tenant_id="tenant_a", k=10)
assert all(r["tenant_id"] == "tenant_a" for r in res), "LEAKAGE"
Prove deletability. Delete one document and one tenant; verify vector counts drop by exactly the expected number and a follow-up query returns nothing from the deleted scope. Time it — deletion latency at realistic scale is a compliance SLA, and some engines soft-delete with delayed compaction.
Capacity-sanity the choice. Vectors × dimension × 4 bytes gives raw index memory (1M × 1024-dim ≈ 4 GB before graph overhead); check it against the chosen engine's deployment size, and note quantization (pb-32) as the lever if memory is the binding constraint.
Schema-first is the whole trick. Namespaces, ACL tags, content hashes, and model versions cost nothing to include at design time and each one saves a full re-index when you need it at month six.
model_version field. The first embedding-model upgrade forces a blind full wipe instead of a versioned cutover.For consulting deliverables, run the whole design exercise against a synthetic two-tenant corpus so the leakage and deletability tests can be demonstrated to the client without touching their data. Default the engine recommendation to what the client already operates (existing Postgres → pgvector; existing warehouse → warehouse-native) because new-system approvals are the slowest path in client environments, and document the tenancy pattern and deletion SLA in the handover — those two answers are what the client's security review will ask for first. If the client mandates a managed service, confirm data-residency region and deletion guarantees in the vendor contract before indexing anything real.