Skip to content
Vol. INo. 4
Auxesis

A weekly digest of Web, Mobile, Backend & AI engineering

Front Page Dispatch This Week’s Edition

Feature Backend Desk

Filtered vector search: where pgvector breaks and what to do

On 100,000 vectors, a 1% filter returned 0.33 of 10 requested rows from pgvector's defaults. The Postgres planner, not the index, decides when that happens.

By Abhishek Prashant · 8 min read
Engraving of a round fine-mesh sieve with a handle, stretched across a web of knotted threads and connected nodes.

The usual question, "pgvector or a dedicated vector database?", is mostly about scale. For anything with a WHERE clause it is about something narrower: who plans the query. On a 100,000-row table with an HNSW index, pgvector 0.8.2 returned an average of 0.33 rows for a LIMIT 10 query filtered to 1% of the data, with no error and the default settings, even with a B-tree on the filter column.

A dedicated engine such as Qdrant makes the equivalent decision inside the engine, using filter cardinality. In Postgres you make it yourself, by choosing indexes and checking plans. Once you do, Postgres handles more filtered workloads than its defaults suggest, and the cases where it does not are specific. The default silently returns too few rows. An HNSW index returns the efsearch nearest candidates (40 by default), and Postgres applies the WHERE clause afterwards. The pgvector README states the…