Vector Database Landscape 2026: Pinecone, Qdrant, Weaviate, Milvus, pgvector
A hardheaded comparison of Pinecone, Qdrant, Weaviate, Milvus, and pgvector: architecture, real costs, hybrid search maturity, and when each wins in production.
At some point in the lifecycle of every RAG system, someone opens the AWS bill and has a quiet internal crisis. You budgeted $200/month for vector storage. The actual charge is $1,100. The vectors are all there, recall hasn't dropped, nothing is obviously broken — but the economics are not what anyone projected, and now you're choosing between a migration and a budget conversation.
The gap usually traces back to a single decision made months earlier: which vector database to use, at what tier, with which index configuration. That decision compound-interests over time. Getting it right requires understanding the actual architecture of each system, not just its marketing positioning.
The four-way split in the 2026 market
By mid-2026, the vector database market has stratified into four distinct categories, each with different economic logic.
Fully managed, no self-hosting option. Pinecone sits here alone. You get a polished API, predictable latency numbers (7ms p99 in single-tenant benchmarks), and zero infrastructure to manage. The premium shows up at scale: at 100M vectors it's a recurring $700–1,200/month line item, 2–4x what a managed open-source tier charges for the same corpus. At small scale — under 5M vectors with moderate query load — the premium is small enough that it's often worth it.
Open-source with a managed tier. Qdrant, Weaviate, and Milvus all fall here. You can self-host on your own infrastructure, run the managed cloud for convenience, or mix — self-host in your primary region, managed cloud for a standby. This flexibility is worth real money if your team has any ops capacity at all.
Database extension. pgvector and pgvectorscale add vector search to an existing Postgres cluster. No new system to operate, no new failure modes to understand, no new vendor relationship. The ceiling is around 100M vectors before query latency becomes a forcing function toward a dedicated system.
Emerging serverless-native databases. LanceDB and Turbopuffer occupy a different architectural niche entirely. LanceDB uses a columnar storage format (Lance) with zero-copy reads, no server process, and embeds directly into your application process. Turbopuffer is designed for multi-tenant workloads at extreme namespace counts (50,000+ namespaces) with per-query rather than per-instance pricing. Neither is a drop-in replacement for the main contenders, but both are worth knowing about if your workload looks like many small tenants rather than one large vector space.
Pinecone: the operational premium
Pinecone's proprietary index delivers consistent low latency, and the serverless tier eliminated the capacity planning problem that plagued earlier pod-based deployments. For a team that wants to ship a RAG prototype to production in a week and has a CTO who will approve $200/month without asking questions, it's a legitimate choice.
The problems emerge at scale. The 7ms p99 Pinecone publishes is measured under ideal conditions: a single client, moderate QPS, well-sized serverless allocation. Real production workloads with concurrent requests, metadata filters, and bursts spike this to 25–50ms. That's not a knock — any system behaves differently under load — but engineers who don't budget for it get surprised.
The second problem is migration risk. Pinecone has no self-hosted option. If you build on it and the economics stop working, migrating 100M vectors to Qdrant or Weaviate is a weekend project at minimum and a multi-week project if your ingestion pipeline is tightly coupled to Pinecone's SDK. Build with the assumption that you might migrate: keep the vector store abstracted behind an interface, not called directly from your retrieval code.
# Pattern: abstract the vector store so you can migrate without touching retrieval logic
from abc import ABC, abstractmethod
from typing import Optional
class VectorStore(ABC):
@abstractmethod
def upsert(self, id: str, vector: list[float], metadata: dict) -> None: ...
@abstractmethod
def query(
self,
vector: list[float],
top_k: int,
filter: Optional[dict] = None
) -> list[dict]: ...
class PineconeStore(VectorStore):
def __init__(self, index_name: str, api_key: str):
from pinecone import Pinecone
pc = Pinecone(api_key=api_key)
self.index = pc.Index(index_name)
def upsert(self, id: str, vector: list[float], metadata: dict) -> None:
self.index.upsert(vectors=[{"id": id, "values": vector, "metadata": metadata}])
def query(self, vector: list[float], top_k: int, filter: Optional[dict] = None) -> list[dict]:
result = self.index.query(vector=vector, top_k=top_k, filter=filter, include_metadata=True)
return [{"id": m.id, "score": m.score, "metadata": m.metadata} for m in result.matches]
Swap PineconeStore for QdrantStore when the bill crosses $500/month, and your retrieval layer never knows the difference.
Qdrant: the operator's favorite
Qdrant has emerged as the practical workhorse of the 2026 mid-tier. It ships as a single binary with no external dependencies, which means a five-minute docker run to a functioning instance. The Rust implementation keeps the footprint small — Qdrant can run usably on 4GB RAM for small collections, whereas Milvus requires etcd and MinIO as dependencies before you index a single vector.
Server-side hybrid search is the feature that matters most in practice. Named vectors have been in Qdrant since v0.10 and sparse vectors since v1.7, but the v1.10 Query API is what made hybrid search a single call: you can store multiple named vector fields per point — dense for your text-embedding-3-large embeddings and sparse for SPLADE — and Qdrant queries both simultaneously, fusing scores internally. This is covered in depth in hybrid search: fusing dense vectors and sparse BM25 correctly; the short version is that you no longer need Elasticsearch alongside your vector store for keyword matching.
from qdrant_client import QdrantClient
from qdrant_client.models import (
VectorParams, SparseVectorParams, Distance,
NamedVector, NamedSparseVector, SearchRequest
)
client = QdrantClient(url="http://localhost:6333")
# Collection with named dense + sparse vectors
client.create_collection(
collection_name="docs",
vectors_config={"dense": VectorParams(size=1536, distance=Distance.COSINE)},
sparse_vectors_config={"sparse": SparseVectorParams()},
)
# Hybrid query: dense + sparse in one call
results = client.query_points(
collection_name="docs",
prefetch=[
{"query": dense_embedding, "using": "dense", "limit": 20},
{"query": {"indices": sparse_indices, "values": sparse_values}, "using": "sparse", "limit": 20},
],
query={"fusion": "rrf"}, # Reciprocal Rank Fusion
limit=5,
with_payload=True,
)
Qdrant's filterable HNSW — the graph gets extra links so traversal survives filtering — comes with a cardinality-based planner that dynamically chooses between full-scan and graph traversal based on the selectivity of your metadata predicate. This matters more than it sounds: naive pre-filtering on high-selectivity predicates (finding the 0.1% of vectors that match user_id = 12345) breaks HNSW graph links and silently destroys recall — a pitfall covered in metadata filtering, scaling, and production cost control.
The Qdrant Cloud managed tier starts at $25/month for 1GB RAM, which covers roughly 100–150K vectors at float32 1536 dims — about 300K if you enable INT8 scalar quantization. It scales to large dedicated clusters; the economics stay favorable compared to Pinecone at most operating points.
Weaviate: native hybrid search without compromise
Weaviate made the most significant hybrid search investment of any vector database in 2025. BlockMax WAND is a BM25 index algorithm that prunes candidate lists during scoring, making keyword search faster without the linear scan penalty of naive BM25. Combined with their Relative Score Fusion (RSF) implementation for blending with dense vector scores, Weaviate can handle hybrid queries that would require a separate Elasticsearch instance in any other architecture. Weaviate is also the vendor that shipped ACORN (v1.27), the filter strategy from the ACORN paper that keeps HNSW traversal alive under selective metadata filters by hopping over non-matching neighbors.
The GraphQL query model is Weaviate's most distinctive — and divisive — design choice. For multi-hop retrieval queries ("find documents about X, then find related documents about Y"), GraphQL expresses the dependency structure naturally. For teams that want a simple k-NN query + metadata filter, it's more ceremony than a REST or gRPC API.
{
Get {
Article(
hybrid: {
query: "vector database performance benchmarks"
alpha: 0.75
}
where: {
path: ["category"]
operator: Equal
valueText: "engineering"
}
limit: 5
) {
title
content
_additional { score explainScore }
}
}
}
Weaviate's multi-tenancy model assigns each tenant their own isolated segment within a shared cluster, with the option to activate/deactivate cold tenants to save RAM. This is built for SaaS products where you have thousands of customers each with small vector collections — keeping inactive tenants on disk while hot tenants run in memory.
The operational complexity is higher than Qdrant. Weaviate's Kubernetes operator is solid, but there's more surface area to configure. Budget 2–3 days for a production-ready cluster setup versus an afternoon for Qdrant.
Milvus: billion-scale open-source
Milvus is the answer to a question most teams aren't asking yet: how do you run a vector database over a billion vectors on infrastructure you control? It's the only system in this comparison that ships sharding, distributed query coordination, and hardware-accelerated index building as a single deployable unit.
The dependency stack is the main operational cost. Milvus requires etcd for metadata coordination, MinIO (or S3) for object storage, and the Milvus query/data/index nodes themselves. That's five or six services to monitor, upgrade, and back up. For teams already running a Kubernetes platform with Helm-based deployments, the incremental cost is manageable. For a three-person startup, it's a serious commitment.
Milvus 2.5 shipped native Sparse-BM25, meaning the engine maintains a sparse inverted index alongside the dense HNSW/IVF index without a separate service. Hybrid queries over a billion vectors without an external keyword store is the specific scenario where Milvus has no serious competition in the open-source space.
flowchart TD
CLIENT[Client] --> PROXY[Milvus Proxy\nload balancing]
PROXY --> QN[Query Nodes\ndense ANN + sparse BM25]
PROXY --> DN[Data Nodes\ningestion + WAL]
PROXY --> IN[Index Nodes\nHNSW / IVF build]
QN --> MINIO[(MinIO / S3\ncolumnar segments)]
DN --> MINIO
IN --> MINIO
PROXY --> ETCD[(etcd\nmetadata + coordination)]
style PROXY fill:#00e5ff,color:#0a0a0f
style QN fill:#0e7490,color:#fff
style DN fill:#0e7490,color:#fff
style IN fill:#0e7490,color:#fff
style MINIO fill:#15803d,color:#fff
style ETCD fill:#a855f7,color:#fff
The Zilliz Cloud managed version of Milvus is an option if you want the Milvus API without the operational complexity. Pricing is in the same bracket as Weaviate Cloud and Qdrant Cloud — meaningfully cheaper than Pinecone at scale.
pgvector: the Postgres path
There's a version of the "which vector database" conversation that ends with "you already have Postgres." If your team is comfortable with Postgres operations, has an existing Postgres cluster with the capacity to add a vector index, and expects to stay under 50M vectors, pgvector with pgvectorscale deserves serious consideration before you add a new database system to your stack.
Vanilla pgvector has well-known limitations: it builds HNSW in memory, has no disk-ANN support, and scales poorly beyond a few million vectors at high QPS. The pgvectorscale extension adds StreamingDiskANN — a disk-resident index that benchmarks at 471 QPS with 99% recall on 50M vectors. That's a real number, not a cherry-picked ideal-condition measurement.
-- Enable extensions
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS vectorscale;
-- Table with embedding column
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
content TEXT,
embedding vector(1536),
metadata JSONB
);
-- StreamingDiskANN index (pgvectorscale)
CREATE INDEX ON documents USING diskann (embedding);
-- Metadata filtering using Postgres WHERE clause
SELECT id, content, 1 - (embedding <=> $1::vector) AS score
FROM documents
WHERE metadata->>'category' = 'engineering'
ORDER BY embedding <=> $1::vector
LIMIT 10;
The ceiling is real. Above 100M vectors, the query latency numbers climb and the RAM requirements for competitive recall become uncomfortable on standard Postgres instance sizes. At that scale, the migration cost to a dedicated vector database is unavoidable — and if you've abstracted your vector store interface properly, it's a weekend of work, not a quarter of work.
There's also no native hybrid search in pgvector. You can combine vector similarity with full-text search using Postgres's built-in tsvector/tsquery, but you're writing the fusion logic yourself and Postgres's keyword search lacks the scoring sophistication of BM25 implementations in dedicated systems.
flowchart LR
SCALE["Vector collection size"] --> D1{"< 10M vectors?"}
D1 -->|Yes| PG["pgvector + pgvectorscale\nTrivial ops, cheapest TCO"]
D1 -->|No| D2{"< 100M vectors?"}
D2 -->|Yes| D3{"Need hybrid search?"}
D3 -->|No| QD["Qdrant\nBest price-perf, easy ops"]
D3 -->|Yes| WV["Weaviate\nBlockMax WAND + RSF"]
D2 -->|No| D4{"Open-source required?"}
D4 -->|Yes| MV["Milvus\nBillion-scale, full ops cost"]
D4 -->|No| D5{"Ops budget = 0?"}
D5 -->|Yes| PC["Pinecone\nFully managed, premium price"]
D5 -->|No| QD2["Qdrant or Weaviate\nself-hosted at scale"]
style PC fill:#00e5ff,color:#0a0a0f
style PG fill:#15803d,color:#fff
style QD fill:#0e7490,color:#fff
style WV fill:#a855f7,color:#fff
style MV fill:#ffaa00,color:#0a0a0f
Worked cost comparison at 10M and 100M vectors
These numbers are illustrative as of mid-2026; pricing drifts and varies by region and tier.
Scenario A: 10M vectors, 1536 dims, 50K queries/day
Raw storage: 10M × 1536 × 4 bytes ≈ 61 GB float32
HNSW overhead: ~92–122 GB in RAM
Option 1: Pinecone Serverless
→ ~$60–120/month (serverless is query + storage metered)
Option 2: Qdrant Cloud (1 node, 32GB RAM)
→ ~$65/month
→ Fits with INT8 quantization (61.44/4 ≈ 15.4 GB + index)
Option 3: pgvector on RDS (r6g.large: 16 GB RAM)
→ ~$140/month instance, vectors in StreamingDiskANN (disk-resident)
→ TCO shared with existing Postgres workload
Option 4: Qdrant self-hosted (32GB RAM EC2: r7g.xlarge)
→ ~$150/month on-demand
→ Adds 2–4h/month ops overhead
At this scale and query volume, Pinecone Serverless is the cheapest
option on pure dollars — the managed-markup story only starts once
query volume and vector count climb (see Scenario B).
Scenario B: 100M vectors, 1536 dims, 500K queries/day
Raw float32: ~614 GB → HNSW in RAM: impractical without quantization
INT8 quantization: ~154 GB → HNSW: ~230 GB
Option 1: Pinecone Serverless
→ $700–1,200/month (volume estimate, varies with query patterns)
Option 2: Qdrant Cloud (dedicated 4-node cluster)
→ $250–400/month
Option 3: Qdrant self-hosted (4x r7g.2xlarge: 64 GB RAM each)
→ INT8 reduces total index to ~230 GB, or ~58 GB/node — 4 nodes cover it
→ ~$1,200–1,250/month on-demand (~$300/node), ~$750/month with 1-yr reserved
→ On-demand is roughly at parity with Pinecone; only reserved pricing
(or spot, if you can tolerate it) beats it — and Qdrant Cloud beats both
Option 4: Milvus on Kubernetes (mixed node pool)
→ $350–500/month depending on node mix
→ Significant ops overhead; justified at billion scale, not 100M
What breaks
Vector databases fail in ways that don't throw exceptions. Recall degrades silently. Latency climbs gradually. Costs spike unexpectedly. Knowing the failure modes in advance is the difference between catching them in load testing and catching them from a user complaint.
HNSW recall drop under aggressive metadata filtering. When you apply a filter that selects fewer than 5–10% of your vectors, HNSW graph traversal runs out of connected candidates that satisfy the filter and returns fewer results than top_k — or pads with low-score results. The filter silently shrinks your recall. Qdrant's filterable HNSW and Weaviate's ACORN both address this dynamically, but you need to measure recall under your actual filter distributions, not just your average query. A filter like user_id = X that selects 0.01% of vectors will destroy naive HNSW recall. This is explained in detail in ANN indexes under the hood: HNSW, IVF, and when each wins.
sequenceDiagram
participant APP as Application
participant VDB as Vector DB (naive pre-filter)
participant IDX as HNSW Index
APP->>VDB: query(vector, filter=user_id:12345, top_k=10)
VDB->>IDX: traverse graph from entry point
IDX->>IDX: candidate: node 7712 — check filter... FAIL
IDX->>IDX: candidate: node 3341 — check filter... FAIL
IDX->>IDX: candidate: node 9102 — check filter... PASS (1)
IDX->>IDX: ... (many graph hops, most filtered out)
IDX-->>VDB: 3 results (ran out of connected nodes)
VDB-->>APP: returns 3 results instead of 10
Note over APP: Silent recall failure — no error thrown
{ "type": "hnsw", "mode": "search", "title": "How HNSW query traversal works" }
Embedding version invalidation. OpenAI deprecated text-embedding-ada-002 and the text-embedding-3-* series uses a different vector space. If you upgrade the embedding model without re-indexing your existing vectors, you're querying with a new model against old embeddings in a space where the distances are meaningless. There's no error. Retrieval quality just silently collapses. Treat embedding model version as part of the collection schema and never mix vectors from different model versions in the same index.
Quantization precision compounding. Binary quantization saves 32x memory and earns its place in most large deployments — but the 2–3% precision loss it introduces compounds. If your queries are already borderline (finding documents with 0.78 cosine similarity from a 0.80 threshold), losing 2–3% precision from quantization plus 1–2% from the ANN approximation may push many correct results below your cutoff. Always measure recall on your actual query distribution, not a synthetic benchmark, before committing to aggressive quantization.
pgvector false ceiling. Teams migrating from pgvector often discover the ceiling not when performance degrades gracefully, but when it falls off a cliff. At 50M vectors, adding pgvectorscale's DiskANN changes the trajectory significantly. The mistake is waiting until 80M+ vectors to investigate the extension, at which point you're simultaneously debugging performance degradation and evaluating a migration.
Pinecone burst latency. Pinecone's serverless tier scales on demand but doesn't pre-warm. A burst of requests after a quiet period can hit cold-path latency (50–150ms) while instances scale. For applications with irregular query patterns — batch processing followed by live user traffic — this latency variance is worth testing explicitly before launch.
The newcomers worth watching
LanceDB takes the most architecturally distinctive approach in the market. The Lance columnar format stores vectors alongside metadata in a single file, enables zero-copy reads, and the database runs as a library inside your application process — no server, no network hop, no port to open. This makes it a strong fit for embedded use cases (edge deployments, serverless functions that need vector search, desktop applications) and for workloads where the query latency of a network round-trip is unacceptable. The trade-off is that multi-process access requires the cloud version, and the ecosystem is younger with fewer production war stories.
Turbopuffer solved a specific problem that every other vector database handles poorly: supporting 50,000+ small vector namespaces without per-namespace compute overhead. The typical use case is a SaaS application where each customer has their own vector space with 10K–100K vectors — far too many namespaces for separate collections in Qdrant or Weaviate to be economical. Turbopuffer's pricing is per-query rather than per-instance, which aligns costs with actual usage in sparse-query multi-tenant scenarios.
OpenSearch 3.0 with GPU vector search via NVIDIA cuVS is the enterprise path for organizations already running OpenSearch for text search that want to add vector search without a new system. The 9.5x performance improvement from GPU acceleration holds up on the right hardware, and if you're already paying for GPU instances for other workloads, the marginal cost of adding vector search is low.
None of these three are ready to replace the primary contenders for general-purpose RAG workloads. Each solves a specific problem well enough to be the right choice for that specific problem.
The decision in practice
The architecture of your retrieval layer — covered end-to-end in the RAG from scratch article — matters more than the specific database choice. A well-designed retrieval layer with clean abstractions can migrate between vector databases in a weekend. A tightly coupled layer that calls Pinecone's SDK directly from your application code becomes expensive to move.
Make the database choice based on three facts, not five criteria:
Your vector count trajectory. If you're at 2M vectors and your roadmap projects 20M in 18 months, pgvector is fine now. If you're projecting 200M, start with Qdrant or Weaviate and skip the pgvector phase. The migration cost at 50M vectors is not trivial.
Your ops capacity. A solo founder should use Pinecone or Qdrant Cloud and pay the premium. A team with a dedicated platform engineer should use Qdrant or Weaviate self-hosted above 10M vectors. The break-even on ops investment versus cloud markup is roughly 60–80M queries/month — below that, managed wins on total cost including engineering time.
Your hybrid search requirement. If your use case involves queries with rare proper nouns, product codes, model numbers, or any text where BM25 outperforms dense retrieval (it often does for exact match), choose a system with native hybrid search from the start. Retrofitting hybrid search onto a pure vector store later is possible but painful. For most general-purpose semantic search, pure dense retrieval is fine and you can always add hybrid later — the hybrid search article covers the decision criteria in detail.
The field hasn't converged on a single winner, and it won't in 2026. Pinecone, Qdrant, Weaviate, and Milvus each lead in their lane. Pick the lane that matches your constraints, build with migration in mind, and revisit the choice when your query count or vector count crosses the next order of magnitude.
Frequently asked questions
▸Which vector database is best for a RAG application in 2026?
For under 10M vectors, pgvector + pgvectorscale on an existing Postgres instance is the cheapest and most operationally simple choice. Qdrant's free tier handles small-to-medium workloads well. Beyond 50M vectors, Qdrant or Weaviate self-hosted give the best price-performance ratio. Pinecone wins when your team has zero ops capacity and can absorb $700+/month at 100M vectors.
▸How much does a vector database cost at 100M vectors?
As of mid-2026: Pinecone Serverless runs roughly $700–1,200/month at 100M vectors of 1536 dims with typical query load. Qdrant Cloud on a dedicated 4-node cluster runs $250–400/month for the same corpus. Self-hosting needs ~230 GB of RAM even with INT8 quantization — about $1,200/month on-demand across four 64 GB nodes, closer to $750 with reserved instances — so at this scale managed open-source, not self-hosting, is usually the cheapest option.
▸Can pgvector scale to production workloads?
pgvector alone stalls at high recall above ~1M vectors. With the pgvectorscale extension, benchmarks show 471 QPS at 99% recall on 50M vectors using the StreamingDiskANN index — 11x faster than vanilla pgvector at the same recall target. The ceiling is around 100M vectors before query latency and memory pressure make purpose-built databases a better trade-off.
▸What is the difference between Weaviate and Milvus for hybrid search?
Weaviate implements BlockMax WAND for BM25, which prunes candidate lists efficiently, and combines it with dense vectors via Relative Score Fusion (RSF). Milvus 2.5+ ships native Sparse-BM25 inside the engine, so sparse and dense indexes are co-located without a separate keyword store. Both handle hybrid search natively; Weaviate's GraphQL API makes multi-stage queries easier to express, while Milvus is faster on billion-scale corpora.
▸What is Qdrant named-vector hybrid search?
Named vectors (in Qdrant since v0.10) let you store multiple independent vector fields per document — for example, one field for dense embeddings and one for sparse (SPLADE) embeddings, supported since v1.7. Since the v1.10 Query API, a single query fans out to both fields and Qdrant fuses the scores server-side with Reciprocal Rank Fusion. It eliminates the need for a separate keyword index while keeping the dense and sparse searches co-located in one service.
▸When should I migrate from a managed vector database to self-hosted?
The economic tipping point is typically 60–80M queries per month or a monthly bill exceeding $500. Below that threshold, the engineering cost of operating a self-hosted cluster (monitoring, upgrades, backups, on-call) outweighs the savings. Above it, moving to self-hosted or managed open-source (Qdrant, Milvus, Weaviate) typically cuts the bill 40–65% versus Pinecone within a quarter of migration effort — reserved instances, not on-demand, are what make self-hosting pencil out.
You may also like
Sandboxing AI Agents: Containers, gVisor, and MicroVMs
Sandboxing AI agents with containers, gVisor, Firecracker microVMs, and Wasm: honest boot and overhead numbers, and why egress filtering matters most.
Long Context vs RAG: The Million-Token Question
When does stuffing a million tokens beat retrieval? The empirics on lost-in-the-middle accuracy, context-stuffing costs, and when RAG still wins at 1M tokens.
Voice AI latency budget: hitting sub-500ms in production
A systematic breakdown of every millisecond in the voice AI pipeline and the specific techniques that compound to sub-500ms time-to-first-audio in production.