Reference: pgvector RAG Store
Composite reference for document RAG on PostgreSQL 18.4 + pgvector 0.8+ (dedicated search instance, 64 GB RAM). ~40M chunks, 1536-dim embeddings, multi-tenant SaaS with RLS.
Schema
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE document_chunks (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
tenant_id uuid NOT NULL,
document_id uuid NOT NULL,
chunk_index int NOT NULL,
content text NOT NULL,
embedding vector(1536) NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (tenant_id, document_id, chunk_index)
);
ALTER TABLE document_chunks ENABLE ROW LEVEL SECURITY;
CREATE POLICY chunks_tenant ON document_chunks
USING (tenant_id = current_setting('app.tenant_id', true)::uuid);Index Tuning (HNSW)
CREATE INDEX document_chunks_embedding_hnsw_idx
ON document_chunks
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- Query-time recall vs latency
SET hnsw.ef_search = 100;| Parameter | Value | Note |
|---|---|---|
m | 16 | Default balance for 1536-dim |
ef_construction | 64 | Build time vs recall |
ef_search | 40-120 | Per-request SET in app |
| Distance | vector_cosine_ops | Matches OpenAI cosine models |
Query Pattern
SELECT id, document_id, content,
embedding <=> $1::vector AS distance
FROM document_chunks
WHERE tenant_id = $2::uuid
ORDER BY embedding <=> $1::vector
LIMIT 20;- Always filter
tenant_idbefore vector sort (RLS + planner). - Partial indexes per large tenant considered above 5M chunks.
- Embedding writes batched;
COPYfor bulk ingest off-peak.
Topology
OLTP primary (accounts, billing)
│
└── Logical replication subset → search instance (chunks only)Search instance sized for HNSW RAM (~2x index size headroom). OLTP not colocated with HNSW build maintenance.
Operations
- Reindex HNSW in maintenance window after major pgvector upgrade.
- Monitor
idx_scanand p95 search latency separately from OLTP SLO. - Tenant delete:
DELETE FROM document_chunks WHERE tenant_id = $1(async job).
Related
- pgvector Basics - extension intro
- IVFFlat vs HNSW Indexes - index choice
- RAG Storage Schema - schema depth
- Reference: Multi-Tenant SaaS - RLS patterns
Stack versions: This page was written for PostgreSQL 18.4 (stable 18, maintenance 17), pgvector 0.8+, PgBouncer 1.x, Patroni 3.x, and PostGIS 3.5+.