Scope & vantage. Assessed mid-2026 for the common case: retrieval for a RAG or semantic-search system — tens of thousands to low hundreds of millions of vectors, metadata filtering that actually matters, and a team that would rather not operate a new distributed system unless the workload forces it. Axes are vector-search-specific and not comparable with any other assessment here. Higher is always better on every axis, including Operational Simplicity (higher = less to run).
1. Executive summary
The first question is not "which vector database" — it is "do I need one yet?" For a large share of production RAG systems the honest answer is no, and the cost of getting it wrong runs in the wrong direction: teams reach for a dedicated engine on reflex, then carry a second datastore, a second backup story, and a second consistency model for a workload their existing Postgres would have served.
pgvector is the default I reach for, and its scores say why: it wins Operational Simplicity, Ingestion & Freshness, Governance and Cost precisely because it is not a new system — it is the transactional database you already run, back up, secure and monitor, with an index type added. The 0.8 release closed its most-cited weakness, filtered search, with iterative index scans. Its ceiling is real, though: single-node Postgres, HNSW/IVFFlat only, and no native way to shard vectors. Past roughly ten million vectors, or when filtering and hybrid search become the product rather than a feature, that ceiling arrives.
When it does, the dedicated engines earn their keep. Qdrant is my default graduation target — the strongest filtered search on this page (its ACORN-style filterable HNSW keeps queries fast even when a filter eliminates almost everything), the lowest single-node tail latency, aggressive quantization, and the simplest operational footprint of the dedicated four. Milvus is the answer at genuine billion-vector scale, where its separated compute/storage and the widest index selection (HNSW, IVF, DiskANN, GPU) pay for its heavier operations. Weaviate leads on built-in hybrid search and integrated vectorizer modules. Pinecone is the choice when the requirement is "no operations at all" and a managed bill is preferable to a rota — serverless, enterprise-governed, and the least tunable of the five by design.
Verdict
pgvector — Adopt as the default for RAG retrieval up to ~10M vectors, and stay there longer than instinct suggests. It reuses everything you already operate; the 0.8 iterative scan fixed the filtering hole that used to force an early exit.
Qdrant — Adopt as the graduation target when pgvector's scale or filtering ceiling arrives. Best filtered search and tail latency here, lightest ops of the dedicated engines.
Milvus — Adopt for scale. The right answer at hundreds of millions to billions of vectors, or when you need GPU/DiskANN indexing — at the cost of the heaviest operations on this page.
Weaviate — Trial when hybrid search and built-in vectorization are the product, not an add-on.
Pinecone — Narrow Use. Adopt when zero operations outweighs tunability and lock-in, and the serverless bill has been modelled against real read/write volume.
Main risk: adopting a dedicated vector database before the workload needs one — paying for a second system, its consistency model, and its operations to solve a problem Postgres had already solved.
2. Positioning
These five are usually lined up as interchangeable "vector databases," which flattens the one distinction that decides most selections: is the vector index a feature of a database you already have, or a system in its own right?
| Dimension | pgvector | Qdrant | Weaviate | Milvus | Pinecone |
|---|---|---|---|---|---|
| What it is | A Postgres extension | Dedicated engine (Rust) | Dedicated engine (Go) | Distributed system (Go/C++) | Managed service |
| Deployment | Your existing Postgres | Single binary; shard by hand | Cluster with modules | etcd + object store + node types | Serverless, nothing to run |
| Filtering model | Iterative index scan (0.8+) | Filter folded into HNSW (ACORN) | Filtered HNSW strategies | Filtered search | Metadata filter |
| Scale sweet spot | ≤ ~10M vectors | Millions → sharded 100M+ | Millions → replicated | 100M → billions | Millions → billions (managed) |
| Hybrid search | DIY (tsvector + RRF in SQL) | Native sparse + fusion | Native, first-class | Multi-vector + sparse | Sparse-dense |
| You operate | Nothing new | One process | A cluster | A distributed system | Nothing |
The pattern in that table is the whole assessment. pgvector and Pinecone sit at the two ends of the operations axis — one because the system is already yours, the other because it is entirely someone else's — and everything in between trades operational weight for capability. Qdrant asks you to run one well-behaved process; Milvus asks you to run a distributed system and rewards you with scale that the others cannot reach.
A note on what these scores are not: they are not an ANN-benchmark leaderboard. Raw recall-at-latency between the dedicated engines is close enough that it rarely decides a real selection — the public ANN-Benchmarks shuffle from release to release, and any of these four will hit the recall and latency a typical RAG system needs. What decides selections is filtering behaviour under selective predicates, operational cost, and how the thing fails at 2 a.m. Those are what the axes below weigh.
3. Radar criteria — the reasoning
Recall @ latency
Qdrant 4.6 — Rust HNSW with consistently the lowest tail latency in independent single-node tests, and quantization that trades a little recall for a lot of memory. Milvus 4.4, highest peak throughput and GPU-accelerated index builds. Pinecone 4.3, strong and consistent behind a managed abstraction. Weaviate 4.2. pgvector 3.6 — perfectly adequate HNSW to roughly ten million vectors, then single-node Postgres becomes the limiter rather than the index.
Filtered search
The axis that decides more RAG selections than raw speed, because real queries are almost always "nearest neighbours where tenant = X and date > Y." Qdrant 4.7 — its filterable HNSW folds the predicate into graph traversal, so a filter that removes 99% of candidates does not collapse recall. Weaviate 4.0 and Milvus 3.9, both competent. Pinecone 4.0. pgvector 3.8 — historically its weakest point, because a pre-0.8 HNSW scan would return too few rows after filtering; iterative index scans in 0.8 largely closed that gap, at the cost of a parameter (hnsw.max_scan_tuples) you now have to tune.
Scale & sharding
Milvus 4.6 — built distributed from the start, separated compute and storage, horizontal scale-out to billions. Pinecone 4.4, serverless scale that is someone else's problem. Weaviate 4.0, sharding plus replication. Qdrant 3.9, real sharding that you place and manage yourself. pgvector 2.6 — the honest floor: single-node, with no native vector sharding, so scaling means Citus, manual partitioning, or a migration. This is the ceiling that graduates teams off it.
Index flexibility
Milvus 4.6 — the widest selection anywhere: HNSW, IVF variants, DiskANN, GPU indexes, SCANN. Qdrant 4.2, HNSW plus scalar/product/binary quantization and the newer TurboQuant (~8× compression). Weaviate 4.0, HNSW/flat/dynamic with PQ/BQ/SQ. pgvector 3.2, HNSW and IVFFlat only, with halfvec/bit compression but no DiskANN or GPU. Pinecone 3.4 — deliberately the least flexible: the index is abstracted away, which is a feature for teams who do not want the knobs and a limitation for teams who do.
Hybrid search
Weaviate 4.5 — first-class hybrid (BM25 + vector with fusion) has been a headline capability for years. Qdrant 4.2 and Milvus 4.2, native sparse vectors and a fusion API. Pinecone 4.0, sparse-dense. pgvector 3.4 — you can absolutely do it, combining tsvector full-text with vector distance and fusing with reciprocal-rank in SQL, but you are building the fusion yourself rather than calling it.
Ingestion & freshness
pgvector 4.4 — this is where being Postgres is a straight win: transactional upserts and deletes, MVCC, read-your-writes, and no separate pipeline to keep an index in sync with a source of truth that already lives in the same database. Milvus 4.2 (streaming ingest, and 2.6 replaced its Kafka/Pulsar dependency with a built-in Woodpecker WAL). Qdrant 4.2, Pinecone 4.1, Weaviate 4.1 — all real-time, with the dedicated engines carrying the usual eventual-consistency-of-the-index caveat.
Operational simplicity (higher = less to run)
Two 4.7s at the extremes for opposite reasons. pgvector 4.7 — there is no new system; you already have the backups, the HA, the monitoring and the on-call. Pinecone 4.7 — there is no system at all; it is somebody else's service. Qdrant 4.4, one single binary to run and shard. Weaviate 3.6, a cluster with modules. Milvus 3.0 — the heaviest here by a distance: etcd, object storage and several node types, mitigated but not erased by Milvus Lite for small deployments and by the 2.6 dependency reduction.
Ecosystem & SDKs
Effectively a tie at the top — every one of these is a first-class citizen in LangChain and LlamaIndex, with maintained clients in the languages that matter. pgvector 4.3 inherits the entire Postgres ecosystem on top. Pinecone 4.3, Qdrant 4.2, Weaviate 4.2 (with built-in vectorizer modules a genuine differentiator), Milvus 4.1. Nobody loses a selection on integration.
Governance & security
pgvector 4.4 — it inherits decades of Postgres: role-based access, row-level security, TLS, and whatever audit and encryption you already run. Pinecone 4.2, enterprise-managed with SOC 2 / HIPAA, RBAC and private networking. Weaviate 3.9 (RBAC and strong native multi-tenancy). Milvus 3.8, RBAC and resource-group isolation. Qdrant 3.6 — RBAC and API keys, maturing, and the least of the five here though rarely a blocker.
TCO / cost efficiency
pgvector 4.6 — near-zero marginal cost when you reuse an existing cluster; the cheapest option until scale changes the equation. Qdrant 4.2, memory-efficient and cheap to self-host. Weaviate 3.8. Milvus 3.6 — powerful but operationally expensive, and the managed Zilliz option moves that cost rather than removing it. Pinecone 3.2 — the managed premium plus lock-in, and a serverless model whose per-read/per-write pricing can surprise a team that modelled it on storage alone.
4. Radar scorecard
How these scores are arrived at — the rings, the 0–5 scale, and the evidence rules — is written up in the radar methodology. This table and the chart below are generated from one file, scorecards.json: the source of truth, machine-readable, and kept separate so two copies of the same numbers cannot drift apart between editions. pgvector is the primary column because "should I leave Postgres?" is the decision this assessment exists to answer. Last reviewed 2026-Q3.
| Criterion | pgvector | Evidence | Risk → mitigation |
|---|---|---|---|
| Recall @ Latency | 3.6 | Adequate HNSW to ~10M vectors; single-node Postgres becomes the limiter beyond | Growth past ~10M → graduate to a dedicated engine |
| Filtered Search | 3.8 | 0.8 iterative index scans fixed the over-filtering hole | Very selective filters → tune hnsw.max_scan_tuples, watch recall |
| Scale & Sharding | 2.6 | Single-node; no native vector sharding | Scale → Citus / partitioning, or migrate to Qdrant / Milvus |
| Index Flexibility | 3.2 | HNSW + IVFFlat; halfvec/bit; no DiskANN or GPU | Memory-vs-recall pressure → a dedicated engine's quantization |
| Hybrid Search | 3.4 | tsvector full-text + vector, fused with RRF in SQL — but you build it | Hybrid as a product feature → Weaviate / Qdrant native fusion |
| Ingestion & Freshness | 4.4 | Transactional upserts/deletes, MVCC, read-your-writes, no sync pipeline | — |
| Operational Simplicity | 4.7 | No new system — existing backups, HA, monitoring and on-call | — |
| Ecosystem & SDKs | 4.3 | First-class in LangChain / LlamaIndex, plus the whole Postgres ecosystem | — |
| Governance & Security | 4.4 | Postgres RBAC, row-level security, TLS, existing audit/encryption | — |
| TCO / Cost Efficiency | 4.6 | Near-zero marginal cost reusing an existing cluster | At scale the compute stops being free → re-model |
Comparator scores (same axis order — Recall, Filtering, Scale, Index, Hybrid, Freshness, Ops, Ecosystem, Governance, Cost). Qdrant: 4.6 / 4.7 / 3.9 / 4.2 / 4.2 / 4.2 / 4.4 / 4.2 / 3.6 / 4.2. Weaviate: 4.2 / 4 / 4 / 4 / 4.5 / 4.1 / 3.6 / 4.2 / 3.9 / 3.8. Milvus: 4.4 / 3.9 / 4.6 / 4.6 / 4.2 / 4.2 / 3 / 4.1 / 3.8 / 3.6. Pinecone: 4.3 / 4 / 4.4 / 3.4 / 4 / 4.1 / 4.7 / 4.3 / 4.2 / 3.2.
5. The radar
Ten vector-search axes; higher is better on all of them. The shapes are the argument. pgvector is a lopsided pentagon — tall on the operational, freshness, governance and cost axes that come free with Postgres, short on scale and index flexibility. Qdrant is the roundest of the dedicated engines. Milvus spikes on scale and index and collapses on ops. Pinecone mirrors pgvector's ops height for the opposite reason and pays for it on cost and flexibility. Click any name in the legend to toggle it — comparing two shapes at a time is far more legible than five at once.
6. Workload-specific analysis
| Situation | Best fit | Notes |
|---|---|---|
| RAG on an app that already runs Postgres | pgvector | One datastore, one backup, one consistency model. Start here. |
| Heavily filtered search (tenant, ACL, recency) | Qdrant | Filter folded into the graph — recall holds when the predicate is selective. |
| Hundreds of millions to billions of vectors | Milvus | Separated compute/storage and DiskANN/GPU indexing. Budget for the ops. |
| Hybrid (keyword + vector) is the product | Weaviate | Native fusion and built-in vectorizers; less to assemble yourself. |
| No platform team; managed is the requirement | Pinecone | Zero ops and enterprise governance — model the serverless bill first. |
| < 1M vectors, latency-relaxed | pgvector | A dedicated engine here is a second system solving a problem you don't have. |
| Adopting one because it's a "vector database" | Stop | The most common reason a dedicated engine gets chosen, and the worst one. |
The trap: buying a vector database before you have the problem it solves. A dedicated engine is a second datastore — its own backups, its own failure modes, its own consistency model, and a synchronisation pipeline to keep its index aligned with the source of truth that usually still lives in your primary database. All of that is worth it when scale, filtering, or hybrid search genuinely exceed what pgvector does — and pure overhead when they don't. The mirror trap is staying on pgvector past its ceiling out of inertia: single-node, no vector sharding, HNSW/IVFFlat only. When your p95 is climbing with your vector count and filters are getting more selective, that is the signal to graduate, and Qdrant is usually where I'd graduate to.
7. Reference architecture
The pattern I would build keeps the retrieval store swappable behind a thin interface, so "start on pgvector, graduate later" is a configuration change rather than a rewrite.
graph LR
SRC[("Source documents")] --> CHK["Chunk + clean"]
CHK --> EMB["Embedding model"]
EMB --> IDX["Index / upsert"]
IDX --> RET["Retriever interface
(swappable backend)"]
RET --> PGV[("pgvector
start here")]
RET -.->|"graduate at scale"| DED[("Qdrant / Milvus / Pinecone")]
Q["Query"] --> QEMB["Embed query"]
QEMB --> RET
RET --> RANK["Filter + rerank"]
RANK --> LLM["LLM answer + citations"]
META[("Metadata / ACL")] -.->|"filter at search time"| RET
The retriever interface is the load-bearing decision. Put the vector store behind one method — search(query_vector, filter, k) — and the choice of engine stops being architectural and becomes operational: you can start on pgvector and swap the backend when the axes above say it is time, without touching the ingestion or the answering side.
The same query, on either side of the graduation — the interface hides which store answers it:
# Start here: pgvector. The vector store IS the app database, so a filtered
# similarity search is one SQL statement — and the filter runs in the same
# query as the ANN scan. Bind parameters; never f-string user input into SQL.
def search_pgvector(qvec, tenant, k=8):
return db.query(
"select id, chunk, embedding <=> %s as dist " # <=> = cosine distance
"from documents where tenant = %s "
"order by embedding <=> %s limit %s",
[qvec, tenant, qvec, k],
)
# Graduate here: Qdrant. Same shape, different backend — the filter is folded
# into the HNSW traversal, so a selective tenant filter stays fast. The
# retriever interface means the calling code never changed.
def search_qdrant(qvec, tenant, k=8):
return client.query_points(
collection_name="documents",
query=qvec,
query_filter={"must": [{"key": "tenant", "match": {"value": tenant}}]},
limit=k,
).points
8. POC plan (4 weeks)
- Week 1 — try to disqualify pgvector first. Load your real corpus at its real size into Postgres with an HNSW index and run your real queries, filters included. If it meets your recall and p95, the assessment is over and you have saved yourself a system. Most teams under ten million vectors stop here.
- Week 2 — test the axis that actually decides it: filtering. Benchmark with your most selective real filter (tenant, ACL, recency), not an unfiltered top-k. This is where pgvector's iterative scan and Qdrant's filterable HNSW separate, and where a naive post-filter benchmark lies to you.
- Week 3 — operate the failure, not the happy path. Kill a node, restore from backup, run a rolling upgrade, rebuild an index. The dedicated engines earn or lose their scores here, and this is the week that tells you the true cost of Milvus versus the true simplicity of a single Qdrant binary.
- Week 4 — model cost at 12-month scale and write the ADR. Project the vector count and query volume forward a year and price each candidate — including Pinecone's per-read/per-write serverless bill and the compute pgvector stops getting for free at scale. Record which engine, at which threshold, you would graduate to.
9. Final recommendation
Default to pgvector, put the vector store behind a retriever interface, and graduate to a dedicated engine only when a specific axis forces it — usually Qdrant, Milvus at billion-scale, Pinecone when you want no operations.
The decision rule I would give a team is one question: is the vector index a feature of a database you already run, or does the workload need a system of its own? For RAG retrieval under about ten million vectors, with filtering that pgvector 0.8's iterative scans now handle, the index is a feature — and adding a dedicated engine buys scale you do not need while costing a second datastore, its consistency model, and its operations. pgvector scores highest here on operations, freshness, governance and cost precisely because none of those are new work.
When the workload does need a system of its own — the vector count crosses into the tens of millions, filters get more selective, or hybrid search becomes the product — Qdrant is the graduation I reach for most: best filtered search and tail latency on this page, and the lightest operations of the dedicated four. Go to Milvus when the scale is genuinely into the hundreds of millions or billions and you need DiskANN or GPU indexing, and budget honestly for its operational weight. Choose Weaviate when native hybrid search and built-in vectorization are worth assembling less yourself, and Pinecone when the absence of any operations outweighs tunability and lock-in — after you have modelled the serverless bill against real traffic.
I would re-assess when pgvector grows native sharding or DiskANN-class indexing — either would push its ceiling up materially and graduate fewer teams off it — and when the dedicated engines' filtered-search approaches converge, which would move the deciding axis somewhere else.
References
Vector-search benchmarks age quickly and vendor pages overstate; I have leaned on release notes and primary docs, and treated any single benchmark as directional rather than settled.
Primary sources
- pgvector 0.8.0 release and the pgvector repository. Iterative index scans, index types, and the distance operators behind the filtering and freshness scores.
- Qdrant — filterable HNSW and the 1.18 release (TurboQuant). The evidence behind the 4.7 filtering score and the quantization scores.
- Milvus 2.6. Woodpecker WAL, distributed architecture, and the index selection behind the scale and index-flexibility scores.
- Weaviate — vector index & hybrid search. The native fusion behind the 4.5 hybrid score.
- Pinecone — serverless architecture. The managed, index-abstracted model behind its ops and flexibility scores.
Background
- ANN-Benchmarks. The neutral recall-vs-latency reference — useful as directional evidence, not a leaderboard to select on.
Deeper reading (blog)
The retrieval engineering behind the scores:
- Fine-tuning vs RAG vs Prompting — when retrieval is the right tool at all.
- Build-Time Knowledge Graphs — when a graph beats a vector index for retrieval.
- Text-to-SQL and the Semantic Layer — the retrieval pattern that is not embeddings.
- Radar: MCP vs Agent Skills vs function calling — how the retriever plugs into an agent.
Scores are my own architect-level judgment for the stated use case, calibrated to mid-2026 — not a vendor ranking, and not an ANN-benchmark result. Vector-search axes, higher is better. NOT comparable with any other assessment here. Re-score against your own POC numbers before you commit.