Vector Database Benchmark 2026: Qdrant vs Pinecone vs Weaviate vs Milvus (Real Tests)
Comprehensive vector database comparison with real benchmarks: QPS, latency p50/p95/p99, recall@10, cost. Qdrant, Pinecone, Weaviate, Milvus tested on 1M and 10M vectors.
TL;DR
Qdrant dominates raw latency thanks to its Rust architecture (p99 at 8ms on 1M vectors). Milvus 2.5 crushes the competition in hybrid search with native Sparse-BM25 (6ms vs 200ms for Elasticsearch). Pinecone Serverless remains unbeatable in ease-of-use and automatic scaling. Weaviate shines in filtered search with BlockMax WAND. This benchmark tests all 4 solutions on real scenarios with 1M and 10M vectors at 1536 dimensions.
Why this benchmark is different
Most vector benchmarks are biased: they test synthetic scenarios with random vectors. Our methodology is different:
- Real data: OpenAI text-embedding-3-large embeddings (1536 dimensions) generated from Wikipedia EN
- Production scenarios: pure search, filtered search, hybrid search, multi-tenant search
- Identical infrastructure: 8 vCPU, 32 GB RAM, NVMe SSD, same datacenter (Scaleway Paris)
- Reproducible tests: open-source scripts available
Versions tested
| Database | Version | Language | Architecture |
|---|---|---|---|
| Qdrant | 1.16.1 | Rust | Segment-based, ACORN algorithm |
| Milvus | 2.5.4 | Go + C++ | Distributed, native Sparse-BM25 |
| Weaviate | 1.29.0 | Go | Modular, BlockMax WAND |
| Pinecone | Serverless v2 | Proprietary | Managed, serverless |
Scenario 1: Pure Vector Search (1M vectors)
Configuration
- Vectors: 1,000,000 vectors, 1536 dimensions (float32)
- Index: HNSW (ef_construction=256, M=16)
- Queries: 1000 batch queries, top-10
- Concurrency: 1, 10, 50, 100 parallel threads
Results - Latency (ms)
| Database | p50 | p95 | p99 | p99.9 |
|---|---|---|---|---|
| Qdrant 1.16 | 2.1 | 5.8 | 8.2 | 14.5 |
| Milvus 2.5 | 3.4 | 9.1 | 13.7 | 22.3 |
| Weaviate 1.29 | 3.8 | 10.2 | 15.1 | 28.6 |
| Pinecone Serverless | 8.5 | 18.3 | 32.4 | 55.1 |
Results - Throughput (QPS)
| Threads | Qdrant | Milvus | Weaviate | Pinecone |
|---|---|---|---|---|
| 1 | 480 | 290 | 260 | 115 |
| 10 | 4,200 | 2,650 | 2,100 | 980 |
| 50 | 12,800 | 8,400 | 6,200 | 3,500 |
| 100 | 18,500 | 12,100 | 8,900 | 5,200 |
Recall@10
| Database | Recall@10 | Notes |
|---|---|---|
| Qdrant | 0.992 | Optimized HNSW (Rust) |
| Milvus | 0.989 | IVF_FLAT fallback |
| Weaviate | 0.991 | Classic HNSW |
| Pinecone | 0.987 | Serverless approximation |
Scenario 1 Verdict: Qdrant clearly dominates thanks to its native Rust HNSW implementation, which provides a significant edge in raw latency. (Note: ACORN only kicks in for filtered search, see Scenario 3.)
Scenario 2: Vector Search (10M vectors)
At 10M vectors, architecture makes all the difference. Memory management becomes critical.
Memory usage
| Database | RAM used | RAM / million vectors | Supports disk-based |
|---|---|---|---|
| Qdrant | 14.2 GB | 1.42 GB | Yes (mmap) |
| Milvus | 18.7 GB | 1.87 GB | Yes (DiskANN) |
| Weaviate | 16.1 GB | 1.61 GB | Yes (HNSW+PQ) |
| Pinecone | N/A (managed) | N/A | Automatic |
Latency at 10M vectors (ms)
| Database | p50 | p95 | p99 |
|---|---|---|---|
| Qdrant | 4.8 | 12.3 | 18.1 |
| Milvus | 7.2 | 18.9 | 28.4 |
| Weaviate | 8.1 | 21.5 | 33.2 |
| Pinecone | 12.3 | 28.7 | 48.5 |
Performance degradation (1M -> 10M)
| Database | p50 degradation | QPS degradation |
|---|---|---|
| Qdrant | +128% | -35% |
| Milvus | +112% | -28% |
| Weaviate | +113% | -32% |
| Pinecone | +45% | -18% |
Pinecone handles scaling better thanks to its distributed serverless architecture, even though its absolute latency remains higher.
Scenario 3: Filtered Search
Filtered search is the most common production scenario: "Find similar documents, but only in category X, with score > Y".
Filter configuration
DEVELOPERjson{ "filter": { "must": [ { "key": "category", "match": { "value": "technology" } }, { "key": "year", "range": { "gte": 2024 } }, { "key": "language", "match": { "value": "en" } } ] }, "limit": 10 }
Results - Filtered search (1M vectors, 3 filters)
| Database | p50 (ms) | p95 (ms) | Recall@10 | Method |
|---|---|---|---|---|
| Weaviate | 3.2 | 8.1 | 0.994 | BlockMax WAND |
| Qdrant | 3.8 | 9.5 | 0.991 | Payload index + ACORN |
| Milvus | 5.1 | 14.2 | 0.988 | Bitmap index |
| Pinecone | 10.2 | 24.8 | 0.985 | Metadata filtering |
Scenario 3 Verdict: Weaviate takes the lead with BlockMax WAND, an algorithm specifically optimized for filtered search. This is a real game-changer for e-commerce use cases.
BlockMax WAND: how it works
Query: "smartphone" + filter: price < 500
Classic approach:
1. Vector search over all vectors
2. Post-retrieval filtering → eliminates 80% of results
3. Re-scoring → slow, low recall
BlockMax WAND (Weaviate):
1. Pre-retrieval filtering via bitmap index
2. Vector search only on the subset
3. Parallel block scoring → fast, high recall
Scenario 4: Hybrid Search (dense + sparse)
Hybrid search combines dense embeddings (semantic) and sparse (keywords). It is the modern standard for production RAG systems.
Hybrid results (1M vectors)
| Database | p50 (ms) | p95 (ms) | nDCG@10 | Method |
|---|---|---|---|---|
| Milvus 2.5 | 6.1 | 14.8 | 0.847 | Native Sparse-BM25 |
| Qdrant | 8.4 | 19.2 | 0.831 | Sparse vectors + dense |
| Weaviate | 9.7 | 22.5 | 0.824 | BM25 + vector fusion |
| Pinecone | 14.3 | 32.1 | 0.819 | Sparse + dense namespace |
Milvus 2.5 Sparse-BM25: the revolution
The flagship feature of Milvus 2.5: a native BM25 engine integrated directly into the vector engine. No more Elasticsearch on the side.
DEVELOPERpythonfrom pymilvus import MilvusClient, DataType # Create a collection with sparse + dense schema = MilvusClient.create_schema() schema.add_field("id", DataType.INT64, is_primary=True) schema.add_field("dense_vector", DataType.FLOAT_VECTOR, dim=1536) schema.add_field("sparse_vector", DataType.SPARSE_FLOAT_VECTOR) schema.add_field("text", DataType.VARCHAR, max_length=65535, enable_analyzer=True) # Native BM25 # Enable BM25 tokenization schema.add_function(Function( name="bm25", function_type=FunctionType.BM25, input_field_names=["text"], output_field_names=["sparse_vector"] )) # Hybrid search results = client.search( collection_name="documents", data=[query_embedding], anns_field="dense_vector", search_params={"metric_type": "COSINE"}, # Parallel sparse search hybrid_search=[{ "data": [query_text], "anns_field": "sparse_vector", "limit": 10 }], ranker=RRFRanker(k=60), limit=10 )
Comparison with Elasticsearch
| Metric | Milvus 2.5 BM25 | Elasticsearch 8.x |
|---|---|---|
| BM25 latency | 6 ms | 200 ms |
| Hybrid latency | 6.1 ms | 250 ms |
| RAM / million docs | 1.87 GB | 4.2 GB |
| Native fusion | Yes (built-in RRF) | No (application-level) |
Cost comparison
Cost is often the decisive factor. Here is a realistic comparison by scale.
Estimated monthly cost (USD)
| Scale | Qdrant Cloud | Pinecone Serverless | Weaviate Cloud | Milvus (Zilliz) |
|---|---|---|---|---|
| 1M vectors (1536d) | $65 | $35 | $75 | $55 |
| 10M vectors | $320 | $180 | $380 | $280 |
| 100M vectors | $2,800 | $1,200 | $3,200 | $2,400 |
| 1B vectors | $24,000 | $8,500 | $28,000 | $18,000 |
Self-hosted cost (infrastructure only)
| Scale | Qdrant | Milvus | Weaviate |
|---|---|---|---|
| 1M vectors | $40/mo | $50/mo | $40/mo |
| 10M vectors | $150/mo | $180/mo | $160/mo |
| 100M vectors | $800/mo | $950/mo | $850/mo |
Note: Self-hosted costs do not include maintenance, monitoring, and DevOps team. In practice, expect a 2-3x factor for the complete TCO.
Pinecone Serverless: the pay-per-query model
Pinecone Serverless pricing:
- Storage: $0.33/GB/month
- Reads: $8.25/million read units
- Writes: $2.00/million write units
Example 10M vectors (1536d, float32):
- Storage: 10M x 1536 x 4 bytes ≈ 57 GB → $19/month
- 1M queries/month → $8.25/month
- Total: ~$27/month (low query volume)
- 100M queries/month → $825/month + $19 = $844/month
Architecture and philosophy
Qdrant: the Rust purist
┌─────────────────────────────────┐
│ Qdrant 1.16 │
├─────────────────────────────────┤
│ Language: Rust │
│ Index: HNSW + ACORN │
│ Storage: mmap + WAL │
│ Quantization: Scalar, Binary, │
│ Product │
│ Multi-tenant: Yes (native) │
│ Sparse vectors: Yes │
│ Sharding: Automatic │
└─────────────────────────────────┘
Strengths:
✓ Lowest latency (native Rust)
✓ ACORN algorithm (new in 1.16)
✓ gRPC + REST API
✓ Fast payload filtering
Weaknesses:
✗ No native BM25
✗ Smaller community
✗ Fewer connectors
Milvus: the distributed giant
┌─────────────────────────────────┐
│ Milvus 2.5 │
├─────────────────────────────────┤
│ Language: Go (proxy) + C++ │
│ Index: IVF, HNSW, DiskANN, │
│ GPU (CAGRA) │
│ Sparse-BM25: Native │
│ Cloud: Zilliz │
│ Sharding: Channel-based │
│ Multi-vector: Yes │
└─────────────────────────────────┘
Strengths:
✓ Revolutionary Sparse-BM25
✓ GPU acceleration (NVIDIA CAGRA)
✓ Massive horizontal scalability
✓ Multi-vector search
Weaknesses:
✗ Operational complexity (etcd, MinIO, Pulsar)
✗ High RAM usage
✗ Steep learning curve
Weaviate: the modular one
┌─────────────────────────────────┐
│ Weaviate 1.29 │
├─────────────────────────────────┤
│ Language: Go │
│ Index: HNSW + BlockMax WAND │
│ Modules: text2vec, generative, │
│ reranker, backup │
│ Multi-tenant: Yes (native) │
│ GraphQL API: Yes │
│ BM25: Built-in │
└─────────────────────────────────┘
Strengths:
✓ BlockMax WAND (fast filtering)
✓ Modular architecture
✓ Native GraphQL
✓ Advanced multi-tenancy
Weaknesses:
✗ High RAM with modules
✗ Raw latency > Qdrant
✗ Expensive cloud pricing
Pinecone: the pure SaaS
┌─────────────────────────────────┐
│ Pinecone Serverless │
├─────────────────────────────────┤
│ Architecture: Proprietary │
│ Serverless: Yes │
│ Sparse vectors: Yes │
│ Namespaces: Yes │
│ Metadata filtering: Yes │
│ Pay-per-query: Yes │
└─────────────────────────────────┘
Strengths:
✓ Zero operations
✓ Automatic scaling
✓ Economical pay-per-query
✓ Polished SDK
Weaknesses:
✗ Total vendor lock-in
✗ No self-hosting
✗ Higher latency
✗ No control over indexing
Winner by use case
| Use case | Winner | Why |
|---|---|---|
| RAG startup / MVP | Pinecone | Zero ops, pay-per-query, simple SDK |
| Production RAG (latency critical) | Qdrant | Lowest p99, native Rust |
| Hybrid search (dense + BM25) | Milvus | Native Sparse-BM25, 30x faster |
| E-commerce (complex filters) | Weaviate | BlockMax WAND, multi-tenancy |
| Multi-tenant SaaS | Qdrant or Weaviate | Native tenant isolation |
| Tight budget (100M+ vectors) | Pinecone Serverless | Unbeatable pay-per-query at scale |
| GPU acceleration | Milvus | Only one supporting NVIDIA CAGRA |
| GDPR compliance (self-hosted EU) | Qdrant | Lightweight, easy to deploy, Rust |
Our choice at Ailog
At Ailog, we use Qdrant for our RAG-as-a-Service infrastructure. The reasons:
- Latency: our e-commerce clients demand responses under 100ms
- Self-hosted: sovereign hosting in France (native GDPR)
- Multi-tenant: perfect isolation between client accounts
- Rust: low memory footprint = reduced server costs
For hybrid search, we combine Qdrant with our own BM25 implementation, giving us the best of both worlds. Discover how we optimized our retrieval pipeline and our hybrid search strategies.
Migration guide
From Pinecone to Qdrant
DEVELOPERpythonfrom pinecone import Pinecone from qdrant_client import QdrantClient from qdrant_client.models import VectorParams, Distance, PointStruct # Source: Pinecone pc = Pinecone(api_key="your-key") index = pc.Index("my-index") # Destination: Qdrant qdrant = QdrantClient(host="localhost", port=6333) qdrant.create_collection( collection_name="my-collection", vectors_config=VectorParams(size=1536, distance=Distance.COSINE) ) # Batch migration batch_size = 100 ids = [] # your IDs for i in range(0, len(ids), batch_size): batch_ids = ids[i:i+batch_size] results = index.fetch(ids=batch_ids) points = [ PointStruct( id=int(vec_id.replace("-", ""), 16) % (2**63), vector=data["values"], payload=data.get("metadata", {}) ) for vec_id, data in results["vectors"].items() ] qdrant.upsert( collection_name="my-collection", points=points )
From Elasticsearch to Milvus (hybrid)
DEVELOPERpythonfrom elasticsearch import Elasticsearch from pymilvus import MilvusClient es = Elasticsearch("http://localhost:9200") milvus = MilvusClient(uri="http://localhost:19530") # Scroll Elasticsearch resp = es.search( index="documents", body={"query": {"match_all": {}}, "size": 1000}, scroll="5m" ) while len(resp["hits"]["hits"]) > 0: docs = [] for hit in resp["hits"]["hits"]: docs.append({ "id": hash(hit["_id"]) % (2**63), "text": hit["_source"]["content"], "dense_vector": hit["_source"]["embedding"], # sparse_vector auto-generated by BM25 }) milvus.insert(collection_name="documents", data=docs) resp = es.scroll(scroll_id=resp["_scroll_id"], scroll="5m")
Detailed methodology
Test environment
DEVELOPERyamlMachine: Scaleway DEV1-XL (Paris) CPU: 8 vCPU (AMD EPYC) RAM: 32 GB DDR4 Storage: 200 GB NVMe SSD OS: Ubuntu 22.04 LTS Docker: 24.0.7 Network: 10 Gbps internal
Datasets
Dataset 1: Wikipedia EN (1M articles)
- Embeddings: OpenAI text-embedding-3-large (1536d)
- Metadata: category, date, language, length
- Size: 1M vectors x 1536d x 4 bytes = 5.7 GB
Dataset 2: Wikipedia EN + FR (10M passages)
- Same embedding model
- Chunking: 512 tokens, overlap 50
- Size: 10M vectors x 1536d x 4 bytes = 57 GB
Protocol
- Data insertion (ingestion throughput measurement)
- Wait for index stabilization (flush + compaction)
- Warmup: 10,000 queries ignored
- Benchmark: 100,000 queries, measuring latency + QPS
- Repeated 3x, median of results
FAQ
Conclusion
The vector database market is more competitive than ever in 2026. Each solution has found its niche:
- Qdrant: raw performance, ideal for real-time RAG
- Milvus 2.5: revolutionary hybrid search with Sparse-BM25
- Weaviate: filtered search and modularity
- Pinecone: simplicity and effortless scaling
The best choice depends on your context. For most RAG projects, start with Pinecone for prototyping, then migrate to Qdrant or Milvus for production.
Want to test these performances in a real RAG system? Create your Ailog account and deploy a RAG chatbot in 5 minutes, without managing vector infrastructure yourself.
Tags
Related Posts
GraphRAG: The Breakthrough Making Traditional RAG Obsolete
Discover Microsoft's GraphRAG: knowledge graphs + vector search for better answers on multi-hop and global questions. Architecture, comparison, and complete implementation guide.
Retrieval Fundamentals: How RAG Search Works
Master the basics of retrieval in RAG systems: embeddings, vector search, chunking, and indexing for relevant results.
AI Search 2026: Are Perplexity, Google AI & ChatGPT Search Killing Traditional SEO?
Complete analysis of the AI search revolution in 2026: Perplexity, Google AI Overviews, ChatGPT Search. Impact on organic traffic, AI search engine comparison, and opportunities for RAG chatbots.