DEV Community

Cover image for Vector Databases for Production RAG (2026): Pinecone vs Qdrant vs Milvus vs pgvector

Vector Databases for Production RAG (2026): Pinecone vs Qdrant vs Milvus vs pgvector

locionic on September 19, 2026

If you are deploying a Retrieval-Augmented Generation (RAG) system in 2026, choosing the wrong vector store can quickly derail your architecture. W...
Collapse
 
ahmetozel profile image
Ahmet Özel •

Good call giving metadata filtering its own section, because that is where these comparisons quietly diverge from production. The numbers people quote are almost always unfiltered recall, and the moment you add a tenant or a date range, the pre-filter versus post-filter choice dominates anything the index itself is doing. Post-filtering with a selective predicate collapses the effective candidate pool, so you lose recall rather than speed, which is the much harder failure to notice.

The axis I would add next to your four: what happens during a reindex. Rebuilding while serving is a real operational property and it differs a lot between these systems.

Collapse
 
locionic profile image
locionic •

The silent recall collapse from post-filtering is far more dangerous than latency spikes because monitoring rarely alerts on it.
I just updated the article with an operational breakdown of reindexing while serving across all four engines (Qdrant's segment merging vs. Milvus's decoupled IndexNodes vs. pgvector's CPU/buffer contention), along with a methodology note on pre/post-filter recall tradeoffs.
Really appreciate the great feedback!

Collapse
 
ahmetozel profile image
Ahmet Özel •

The reindexing breakdown is a useful addition because recall under a selective filter can change while background work also shifts latency. I would report the eligible-candidate count beside filtered recall, so a genuinely sparse subset is distinguishable from candidates lost by the query plan.

For the before-and-during comparison, keeping the same queries and filter predicates would make the result easier to interpret. It would also help to include an exact filtered reference for a small sample, rather than relying on healthy latency or an unfiltered baseline as evidence that the filtered result stayed intact.

Thread Thread
 
locionic profile image
locionic •

Fair point. Reporting eligible candidate counts definitely separates raw data sparsity from query plan loss
I just added that to the methodology section, along with an exact flat-scan reference check to verify filtered recall during reindexing
Thanks again for the great follow-up!

Thread Thread
 
ahmetozel profile image
Ahmet Özel •

The flat-scan reference makes that comparison much easier to interpret. I would freeze the eligibility predicate and corpus snapshot for both paths, since a background update that changes which documents qualify can otherwise look like an ANN recall regression.

One additional field worth keeping is the index generation used by each query. That lets a recall dip be tied to the old index, the rebuilding index, or the handover itself rather than being averaged across all three.

Thread Thread
 
locionic profile image
locionic •

Great catch. Without freezing the corpus and tracking index generations per query, it's way too easy to confuse background mutations or handover hiccups with actual ANN recall loss
Just added both to the methodology section. Really appreciate the follow-up!

Collapse
 
max_quimby profile image
Max Quimby •

Glad you're covering the metadata-filtering overhead explicitly, because that's where most "which vector DB" comparisons quietly cheat — they benchmark unfiltered ANN recall, which is the query almost nobody runs in production. The moment you add tenant_id = X AND status = active in front of the HNSW traversal, the pre-filter vs post-filter decision dominates your latency and recall far more than the raw index choice does. A graph that's beautifully navigable in the aggregate can strand you in a sparse neighborhood once a selective filter prunes it, and then you're silently returning fewer-than-k results and calling it a day.

The pgvector-vs-dedicated call, in our experience, comes down less to benchmark numbers and more to a boring operational question: how much do you value keeping vectors transactionally consistent with the rows they describe? If your embeddings are derived from records that live in Postgres anyway, pgvector saves you an entire class of "the vector store and the source of truth disagree" bugs — and that dual-write reconciliation cost rarely shows up in a latency chart. At millions of multi-tenant vectors the dedicated engines earn their keep, but the crossover point is higher than most greenfield teams assume.

Would be curious whether your benchmarks used pre- or post-filtering for the metadata numbers — the answer changes the whole ranking.

Collapse
 
locionic profile image
locionic •

Benchmarks used post-filtering, which definitely flatters the numbers. Pre-filtering on HNSW with a selective predicate is where recall silently degrades, and that's the case that actually matters in production. On pgvector vs dedicated: fully agree the crossover is higher than people assume. Under ~5M vectors with existing Postgres infra, the dual-write consistency you avoid is worth more than the latency delta.
Will add a note on the filtering method to the benchmark section.