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.
Search across all documentation pages
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.
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);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 |
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;tenant_id before vector sort (RLS + planner).COPY for bulk ingest off-peak.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.
idx_scan and p95 search latency separately from OLTP SLO.DELETE FROM document_chunks WHERE tenant_id = $1 (async job).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+.
Reviewed by Chris St. John·Last updated Jul 18, 2026