pgvector Indexing: HNSW vs IVFFlat

PostgreSQL
pgvector
AI
Database
When to use HNSW and when to use IVFFlat for vector similarity search in PostgreSQL — and what the tradeoffs actually mean in practice.
Author

Aakriti Dhakal

Published

October 1, 2025

pgvector gives you two index types: HNSW and IVFFlat. The docs tell you they exist; they’re less clear on when to choose each. Here’s what the tradeoffs mean in practice.

The short version

  • HNSW: Better recall, faster queries, higher memory cost, slower build time. Default choice for most applications.
  • IVFFlat: Lower memory, faster builds, worse recall unless you tune it. Better for very large datasets where you can’t afford HNSW’s memory overhead.

HNSW

Hierarchical Navigable Small World graphs navigate a multi-layer graph structure to find approximate nearest neighbors. Once built, queries are fast and recall is high.

CREATE INDEX ON document_chunks
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
  • m: Number of connections per node. Higher = better recall, more memory. Default 16 is fine for most cases.
  • ef_construction: Search width during index build. Higher = better recall, slower build. 64–128 is typical.

At query time, set hnsw.ef_search to control the recall/speed tradeoff:

SET hnsw.ef_search = 100;
SELECT * FROM document_chunks
ORDER BY embedding <=> query_embedding
LIMIT 10;

IVFFlat

Inverted file index with flat quantization. Clusters vectors into lists buckets at build time; queries search probes buckets.

CREATE INDEX ON document_chunks
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);

Rule of thumb: lists = rows / 1000 for datasets under 1M rows, sqrt(rows) for larger.

At query time:

SET ivfflat.probes = 10;

More probes = better recall, slower queries. IVFFlat requires the table to be populated before building — you can’t build it on an empty table and add rows later without degrading recall.

Recall testing

Always test recall for your specific dataset. Generate a set of queries with known ground truth (exact kNN via sequential scan), run your index queries, and measure overlap.

-- Exact nearest neighbors (no index)
SET enable_indexscan = off;
SELECT id FROM document_chunks
ORDER BY embedding <=> $1
LIMIT 10;

Performance table

Threads Metric HNSW IVFFlat
Build time — Slow Fast
Query speed — Fast Medium
Recall@10 — ~99% ~95%*
Memory — High Low

*with probes = 10 on a well-tuned index