
Qdrant vs Chroma vs pgvector: Picking the Right Vector DB for Self-Hosted RAG
The Qdrant vs Chroma vs pgvector decision boils down to a three-way trade-off: purpose-built speed, prototyping simplicity, or staying inside Postgres. Each approach works, the question is which trade-off fits your RAG pipeline.
Quick Summary: Which Vector Database Should You Choose?
Choose Qdrant if you need production-grade vector search with advanced filtering, multi-tenancy, and you don't mind running a separate service.
Choose Chroma if you're prototyping, want zero-config local development, or need to go from idea to working RAG in under an hour.
Choose pgvector (+ pgvectorscale) if you already run PostgreSQL and want vector search without adding infrastructure, especially now that pgvectorscale's StreamingDiskANN index has closed the performance gap.
| Feature | Qdrant | Chroma | pgvector (+ pgvectorscale) |
|---|---|---|---|
| Language | Rust | Rust core, Python API | C (Postgres extension) |
| Index types | HNSW, quantization | HNSW | HNSW, IVFFlat, StreamingDiskANN |
| Hybrid search | Dense + sparse vectors | Dense only | Full-text + vector via SQL |
| Metadata filtering | Pre-filter (during search) | Post-filter | SQL WHERE clauses |
| Setup complexity | Docker container | pip install | Postgres + CREATE EXTENSION |
| Scaling | Horizontal sharding | Single-node | Vertical (read replicas possible) |
| Self-hosted cost | Free (Apache 2.0) | Free (Apache 2.0) | Free (PostgreSQL license) |
| Managed option | Qdrant Cloud | Chroma Cloud | Neon, Supabase, Timescale |
| Best for | Production RAG at scale | Prototypes and local dev | Postgres-native stacks |
If you're building a RAG application from scratch, the rest of this post will help you pick the right foundation.
Performance: How Fast Is Each Database?
Performance matters once you go beyond a few thousand documents. Here's where these three diverge significantly.
Qdrant
Qdrant is built from the ground up for vector search. Its Rust implementation and custom HNSW index deliver consistently low latency, benchmarks show query latency around 94ms even under concurrent load. It supports scalar, binary, and product quantization to compress vectors and speed up search while keeping recall above 95%.
Where Qdrant really shines is filtered search. Unlike databases that find nearest neighbors first and then filter, Qdrant's filterable HNSW respects metadata constraints during graph traversal. That means you don't lose recall when combining vector search with filters like category = "technical" or date > 2025-01-01.
Chroma
Chroma's 1.0 release rewrote the core in Rust, delivering 3-5x faster writes and queries compared to the original Python implementation. A follow-up update in August 2025 added base64 vector encoding for another 70% throughput boost.
For datasets under a million vectors, Chroma is genuinely fast. It runs embedded in your Python process with no network overhead, which makes local iteration snappy. But it's a single-node database, there's no built-in sharding or replication.
pgvector + pgvectorscale
This is the dark horse. Vanilla pgvector with HNSW is 5,250x faster than a sequential scan, and pgvector 0.8.0 added iterative index scanning to solve the overfiltering problem that plagued earlier versions.
But the real story is pgvectorscale. Timescale's extension adds the StreamingDiskANN index, inspired by Microsoft's DiskANN research, which stores the index on disk instead of RAM. On a benchmark of 50 million Cohere embeddings (768 dimensions), pgvectorscale hit 471 QPS at 99% recall. That's 11.4x higher throughput than Qdrant's 41 QPS at the same recall level, and 28x lower p95 latency than Pinecone's storage-optimized index.
The catch? These benchmarks used a beefy EC2 instance. Your mileage depends on hardware. But the trajectory is clear: PostgreSQL is no longer the "good enough" option for vector search, it's genuinely competitive.
Verdict: pgvector + pgvectorscale wins on raw benchmark numbers. Qdrant wins on filtered search performance. Chroma is fast enough for prototypes but isn't built for scale.
Setup and Developer Experience
How quickly can you go from zero to vectors?
Qdrant: Docker and Go
Qdrant needs its own container:
docker run -p 6333:6333 -v $(pwd)/qdrant_storage:/qdrant/storage qdrant/qdrantThen insert vectors via the REST API or one of the official SDKs (Python, Rust, Go, TypeScript):
from qdrant_client import QdrantClient
from qdrant_client.models import VectorParams, Distance
client = QdrantClient(url="http://localhost:6333")
client.create_collection(
collection_name="documents",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
)Qdrant's dashboard at localhost:6333/dashboard is a nice touch, you can browse collections, run queries, and inspect payloads visually. The dev-to-production path is clean: your local Docker setup works identically on a production server or Qdrant Cloud.
Chroma: pip Install and Done
Chroma wins the simplicity race by a wide margin:
import chromadb
client = chromadb.Client() # In-memory, zero config
collection = client.create_collection("documents")
collection.add(
documents=["Your RAG document here"],
ids=["doc1"]
)No Docker. No server. It even handles embedding generation automatically if you don't provide vectors. For a RAG prototype, you can go from pip install chromadb to a working search in under 10 lines.
When you're ready for persistence, switch to chromadb.PersistentClient(path="./chroma_data"). For multi-process or networked access, Chroma has a server mode, but at that point, you're starting to lose the simplicity advantage.
pgvector: SQL All the Way
If Postgres is already in your stack, pgvector is a one-liner:
CREATE EXTENSION vector;
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT,
embedding vector(1536)
);
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);Everything is SQL. Your embeddings live next to your application data in the same transaction. There's no sync pipeline, no separate credentials, no extra service to monitor. If you're already running PostgreSQL in production, this is the path of least resistance.
Adding pgvectorscale on top is straightforward if you use Timescale's Docker image or a managed Postgres provider that supports it:
CREATE EXTENSION vectorscale;
CREATE INDEX ON documents USING diskann (embedding);The downside? SQL isn't as ergonomic as Qdrant's payload filtering DSL or Chroma's Pythonic API. And you'll need to manage your own embedding pipeline, pgvector doesn't generate embeddings for you.
Verdict: Chroma wins for fastest prototype. pgvector wins if Postgres is already in your stack. Qdrant has the best balance of DX and production readiness.
Scaling and Production Readiness
Prototyping is one thing. Running a RAG pipeline that handles millions of vectors with consistent latency is another.
Qdrant: Built to Scale Horizontally
Qdrant supports horizontal sharding out of the box. You can distribute collections across multiple nodes, with configurable replication factors for high availability. Its 2026 roadmap includes read-write segregation and block storage integration for even better scaling.
Multi-tenancy is a first-class feature. You can partition data by tenant using payload-based filtering without creating separate collections, which keeps resource usage efficient. For AI agent memory systems handling multiple users, this is a meaningful advantage.
The operational story is solid: built-in backups, metrics endpoints for Prometheus, and WAL-based crash recovery. Qdrant is designed to be self-hosted in production.
Chroma: Single-Node Ceiling
Chroma is honest about its limits. It's a single-node database focused on simplicity and local development. There's no built-in sharding, no replication, and no clustering.
Chroma Cloud went generally available in early 2026 as a serverless, distributed managed option, so you can offload horizontal scale there instead of running it yourself. But the self-hosted, open-source story is still primarily "one server, one Chroma instance." If your dataset fits on a single machine (up to a few million vectors depending on dimensionality), that's fine. Beyond that, self-hosted Chroma hits a wall and you're choosing between Chroma Cloud and a migration.
pgvector: Scales with Postgres
pgvector inherits PostgreSQL's battle-tested scaling story. You get read replicas, connection pooling via PgBouncer, and logical replication. Managed providers like Neon and similar serverless Postgres platforms make vertical scaling almost effortless.
pgvectorscale's StreamingDiskANN index is the key unlock for scale. Because it stores the index on disk (SSDs) rather than RAM, you can handle datasets that would otherwise require expensive high-memory instances. At 50 million vectors, it's already competitive with purpose-built vector databases.
The limitation is horizontal sharding. PostgreSQL doesn't natively shard like Qdrant does. Solutions like Citus exist but add complexity. For most self-hosted RAG workloads under 100M vectors, vertical scaling with pgvectorscale is sufficient.
Verdict: Qdrant wins for horizontal scaling and multi-tenancy. pgvector wins for using existing Postgres infrastructure. Chroma isn't designed for production scale.
Cost of Self-Hosting
All three are open-source and free to run. The real cost is infrastructure and engineering time.
| Scenario | Qdrant | Chroma | pgvector |
|---|---|---|---|
| 100K vectors (prototype) | $0 (laptop) | $0 (laptop) | $0 (existing Postgres) |
| 1M vectors (startup) | $50-100/mo VPS | $50-100/mo VPS | $0 extra (existing Postgres) |
| 10M vectors (growth) | $100-200/mo (4GB+ RAM) | $150-250/mo (needs RAM) | $50-150/mo (pgvectorscale, SSD) |
| 50M+ vectors (scale) | $300-600/mo (sharded) | Not recommended | $200-400/mo (pgvectorscale) |
pgvector has a structural cost advantage: if you're already paying for Postgres, adding vector search is essentially free until you need dedicated resources. There's no extra container, no extra monitoring, no extra backup strategy.
Qdrant's resource usage is efficient for its feature set, but it's a separate service, you'll need to factor in the operational overhead of running and monitoring another piece of infrastructure.
Chroma is cheapest at the prototype stage (zero infrastructure) but becomes the most expensive path if you try to scale it beyond what a single node can handle.
For deploying these on cloud platforms, Qdrant and pgvector both have straightforward Docker-based deployments. Chroma works too, but you lose the embedded simplicity that's its main selling point.
Verdict: pgvector wins on total cost of ownership. It eliminates an entire service from your stack. Qdrant is reasonably priced for what it offers. Chroma's cost story only works during prototyping.
Filtering and Hybrid Search
RAG isn't just "find the nearest vector." You need to combine similarity search with metadata filters, date ranges, access controls, and sometimes keyword matching.
Qdrant: The Filtering King
Qdrant's payload filtering happens during HNSW traversal, not after. That's a critical distinction. Post-filtering can drop your result count below what you asked for; pre-filtering guarantees you get k results that match your constraints.
The filtering DSL is expressive:
from qdrant_client.models import Filter, FieldCondition, MatchValue
results = client.search(
collection_name="documents",
query_vector=embedding,
query_filter=Filter(
must=[
FieldCondition(key="category", match=MatchValue(value="engineering")),
FieldCondition(key="year", range=Range(gte=2024)),
]
),
limit=10,
)Qdrant also supports native hybrid search with both dense and sparse vectors in the same query, which is useful for combining semantic understanding with keyword precision.
Chroma: Basic but Usable
Chroma supports metadata filtering with where clauses:
results = collection.query(
query_embeddings=[embedding],
where={"category": "engineering"},
n_results=10,
)It works for simple cases, but filtering happens after the vector search. With restrictive filters and small datasets, you might get fewer results than expected. There's no sparse vector support or built-in hybrid search.
pgvector: SQL Is Your Superpower
pgvector inherits the full power of SQL for filtering:
SELECT content, embedding <=> $1 AS distance
FROM documents
WHERE category = 'engineering'
AND created_at > '2024-01-01'
AND content @@ to_tsquery('RAG & retrieval')
ORDER BY distance
LIMIT 10;That last line combines vector similarity with PostgreSQL's built-in full-text search in a single query. No external search engine needed. You can join against your users table for access control, aggregate results, use CTEs, anything SQL can do.
pgvector 0.8.0's iterative scanning helps too. If the initial HNSW scan doesn't return enough filtered results, it automatically continues searching rather than returning a partial set.
Verdict: Qdrant wins for complex metadata filtering at scale. pgvector wins for hybrid search flexibility (SQL + full-text + vector in one query). Chroma's filtering is adequate for prototypes only.
When to Use Each: Decision Framework
| If your project needs... | Choose | Why |
|---|---|---|
| Fastest prototype possible | Chroma | Zero config, embedded, automatic embeddings |
| Production RAG with complex filters | Qdrant | Pre-filtering HNSW, multi-tenancy, horizontal scaling |
| Vector search in an existing Postgres app | pgvector | No new infrastructure, ACID transactions, SQL joins |
| 50M+ vectors on a budget | pgvector + pgvectorscale | StreamingDiskANN uses SSD not RAM, 75% cheaper |
| Multi-tenant SaaS with per-user RAG | Qdrant | Native tenant isolation with payload partitioning |
| Local AI dev with Ollama | Chroma | Embeds in your Python process, no Docker needed |
| Regulatory compliance (data in one DB) | pgvector | Everything in Postgres, one audit surface |
| Sparse + dense hybrid retrieval | Qdrant | Native sparse vector support |
Here's the decision tree version: Does your app already use Postgres? If yes, start with pgvector, you can always migrate later if you outgrow it. If no, are you prototyping or building for production? Prototyping goes Chroma. Production goes Qdrant.
The "start simple, migrate later" approach is valid because all three support standard embedding formats. Moving vectors between them is a data migration, not an architecture rewrite.
The pgvectorscale Factor: Why Postgres Is Catching Up
Worth dwelling on this because it changes the calculus for a lot of teams.
Before pgvectorscale, the knock on pgvector was always "it works fine under a million vectors, but it doesn't scale." That was true. HNSW indexes live entirely in RAM, and once your dataset exceeds available memory, performance falls off a cliff.
StreamingDiskANN changes the equation. By storing the graph index on SSD instead of RAM, pgvectorscale handles 50 million vectors at 471 QPS with 99% recall. Statistical Binary Quantization (SBQ) compresses vectors with minimal accuracy loss, recall drops from 98.6% to 96.5% even with aggressive compression.
The practical impact: a team running a RAG pipeline on Postgres no longer needs to plan a migration to a dedicated vector database "when things get serious." For many workloads, pgvector + pgvectorscale is the serious option.
That said, pgvectorscale isn't a silver bullet. It's a TigerData (formerly Timescale) extension, so you need either their Docker image or a provider that bundles it. A 2026 release added label-based filtered vector search to StreamingDiskANN, inspired by Microsoft's Filtered DiskANN research, which narrows Qdrant's long-standing lead on filtered queries. But if you need multi-tenant isolation or native sparse-vector support, Qdrant still has the edge.
How Techsy Approaches Vector Database Selection
When we build RAG pipelines for clients, our evaluation process looks like this:
- Audit the existing stack. If the team already runs Postgres, pgvector is the default starting point. No point adding infrastructure complexity unless there's a clear reason.
- Profile the query patterns. Heavy metadata filtering with high-cardinality fields? That pushes toward Qdrant. Simple semantic search? pgvector or Chroma is fine.
- Estimate scale trajectory. Under 5M vectors and staying there? Any option works. Planning for 50M+? pgvectorscale or Qdrant, depending on step 2.
- Check the team's ops capacity. A two-person startup shouldn't be managing a Qdrant cluster. A managed Postgres provider with pgvector is usually the right call.
We've built production RAG systems with all three. The honest answer is that the database choice matters less than your chunking strategy, embedding model, and retrieval pipeline design. If you're spending more time debating Qdrant vs pgvector than testing different chunk sizes, you're optimizing the wrong thing.
Need help designing a RAG pipeline? Vector-store selection and retrieval design are part of our AI integration service. Reach out and we'll help you pick the right foundation and build the layer around it.
Frequently Asked Questions
Is pgvector good enough for production RAG?
Yes, especially with pgvectorscale. The StreamingDiskANN index handles 50M+ vectors with 99% recall at throughput levels that beat dedicated vector databases in benchmarks. If you already run Postgres, there's rarely a reason to add a separate vector database for RAG.
Can Chroma scale to millions of vectors?
Chroma can handle a few million vectors on a single node with enough RAM, but it has no built-in horizontal scaling. For datasets beyond what a single machine can hold, you'll need to migrate to Qdrant, pgvector, or a managed service.
Does Qdrant support hybrid search with keywords?
Yes. Qdrant supports both dense and sparse vectors in the same collection. You can run hybrid queries that combine semantic similarity (dense) with keyword matching (sparse) and control the weighting between them.
How much RAM do I need for each database?
It depends on vector count and dimensions. As a rough guide: 1M vectors at 1536 dimensions takes about 6GB in Qdrant or pgvector with HNSW. Chroma uses slightly more due to Python overhead. pgvectorscale's DiskANN index dramatically reduces RAM needs by storing the index on SSD.
Can I migrate between these databases later?
Yes. All three work with standard float arrays, so vectors are portable. You'll need to re-create indexes and adapt your query layer, but it's a data migration, not a rewrite. Most migration tools like Qdrant's official migration tool simplify this.
Which one works best with LangChain and LlamaIndex?
All three have official integrations with LangChain and LlamaIndex. Chroma is often the default in tutorials, making it the smoothest for getting started. Qdrant and pgvector integrations are equally mature for production use. Check our guide on the best RAG tools for a broader look at the ecosystem.
Should I use pgvector or pgvectorscale?
Use both. pgvector provides the core vector type and HNSW index. pgvectorscale adds StreamingDiskANN on top for better performance at scale. They're complementary extensions, not alternatives.
Is Qdrant free to self-host?
Completely free under the Apache 2.0 license. Qdrant Cloud is the paid managed option, starting with a free 1GB tier. For self-hosting, you only pay for the compute infrastructure.
What about Milvus or Weaviate instead?
Both are solid alternatives. Milvus is stronger at very large scale (billion+ vectors) with GPU acceleration. Weaviate has a nice built-in vectorization pipeline. But for self-hosted RAG under 100M vectors, Qdrant, Chroma, and pgvector cover the vast majority of use cases with less operational complexity.
Can pgvector handle concurrent RAG queries in production?
Yes. PostgreSQL is designed for concurrent workloads. pgvector inherits connection pooling (PgBouncer), read replicas, and MVCC concurrency control. For high-throughput RAG, pair pgvector with a connection pooler and tune shared_buffers and effective_cache_size.
Final Verdict
| Category | Winner | Key Reason |
|---|---|---|
| Raw performance (large scale) | pgvector + pgvectorscale | 471 QPS at 99% recall on 50M vectors |
| Filtered search | Qdrant | Pre-filtering HNSW, native sparse vectors |
| Setup speed | Chroma | Zero config, pip install, embedded mode |
| Hybrid search | pgvector | SQL + full-text + vector in one query |
| Horizontal scaling | Qdrant | Built-in sharding and replication |
| Total cost of ownership | pgvector | No extra infrastructure if you run Postgres |
| Multi-tenancy | Qdrant | Payload-based tenant isolation |
| Production readiness | Qdrant | WAL recovery, metrics, backups built in |
| Prototyping speed | Chroma | Fastest path from idea to working search |
Overall: For most self-hosted RAG pipelines, pgvector + pgvectorscale is the pragmatic choice. It's fast enough, it scales to tens of millions of vectors, and it keeps your stack simple. You already know SQL. Your team already manages Postgres. One less service means one less thing to break at 2 AM.
If you need advanced filtered search, multi-tenancy, or you're building a product where vector search is the core feature (not a supporting capability), Qdrant is the right investment. It's the most full-featured open-source vector database for a reason.
Chroma earns its place as the prototyping tool. Use it to validate your RAG approach, test different chunking strategies, and iterate on retrieval quality. When you're ready for production, migrate to whichever of the other two fits your stack.
The best advice? Stop debating and start building. Pick pgvector if you have Postgres, Qdrant if you don't, and get your RAG pipeline working. You can always switch the vector store later, the embedding model, chunk strategy, and retrieval logic matter far more.