AI + database

Production pgvector Performance Review

Vector-search performance is a database trade-off problem too: recall, latency, memory, index build cost, metadata filters and the relational workload around the vector search.

HNSW vs IVFFlat

Choose and tune based on workload, recall/latency target, update pattern and operational constraints—not popularity.

Hybrid filtering

Investigate metadata selectivity, query shape and vector-index interaction when filters destroy expected latency.

Memory + builds

Understand index build/maintenance cost, memory pressure and the effect of growth on vector workload behavior.

Typical questions

  • Why did latency change after vector count grew?
  • Should this workload use HNSW or IVFFlat?
  • Why does metadata filtering make ANN behavior worse?
  • How should recall, latency and operational cost be measured together?
  • Is the bottleneck vector indexing, relational filtering or application architecture?

Start with the HNSW versus IVFFlat benchmark guide. The semantic search API guide covers the application architecture and production checks. On 0.8.6 or earlier, read the pgvector 0.8.7 security fix guide first.

How the planner and the vector index interact

A vector index is only one access path the PostgreSQL planner can choose. The plan, not the index definition, decides what the query actually does.

  • The index needs the right query shape. pgvector's approximate indexes are used for ORDER BY embedding <op> $1 LIMIT k, with the distance operator matching the index operator class (for example <=> with vector_cosine_ops). An expression around the distance, a descending sort or a missing LIMIT means no index scan.
  • Filters run after the approximate scan. With the default hnsw.ef_search of 40 and a filter matching 10% of rows, pgvector's documentation notes only about four rows survive on average. The query asked for ten and returns fewer, quickly.
  • The planner may skip the vector index. With a selective filter, a B-tree on the filter column plus an exact distance sort over the remaining rows can be both faster and exact. That is often the right plan; check it is chosen for the right reason.
  • Iterative scans change the trade-off. Since pgvector 0.8.0, hnsw.iterative_scan and ivfflat.iterative_scan let a filtered query keep scanning until enough rows match, bounded by settings such as hnsw.max_scan_tuples. That improves result count at a latency cost that needs measuring.
  • Few distinct filter values suit a partial index per value; many values (such as tenants) usually point to partitioning or a different design.

The evidence is EXPLAIN (ANALYZE, BUFFERS) for representative filtered queries, the returned row count against the requested k, and recall against an exact-search baseline. The filtered-search lab measures each fix on one dataset.

What changes as vector count grows

  • HNSW build time and memory. Builds are much faster while the graph fits in maintenance_work_mem. PostgreSQL logs a notice when it no longer fits, and the build slows sharply from that point. Raising the setting has to leave memory for the rest of the server.
  • Index size versus cache. Once the index no longer fits in memory alongside the hot relational data, latency becomes I/O-bound and less predictable. Compare index size with instance memory, and watch buffer reads in the plans.
  • IVFFlat lists go stale. Lists are fixed at build time from the data present then. pgvector suggests rows / 1000 lists up to a million rows and sqrt(rows) above that. After heavy growth or distribution shift, recall can drift until the index is rebuilt.
  • Writes and maintenance. HNSW inserts cost more than a B-tree insert, and updates and deletes leave work for vacuum. A write-heavy embedding pipeline can compete with query latency.
  • Dimensions and type. vector indexes support up to 2,000 dimensions and halfvec up to 4,000. Half precision halves storage and index size; measure its recall effect before switching.

Version-specific details from the pgvector documentation (0.8.x), checked 13 October 2026. Managed services may ship an older pgvector; check SELECT extversion FROM pg_extension WHERE extname = 'vector'; first.

Production evidence

Need a second set of eyes on a pgvector workload?

Bring the workload shape, vector/index configuration and query behavior. The first step is deciding whether a focused review is justified.

Prefer to talk first? Book a 20-minute triage call.