---
title: "Vector database for RAG: how to choose one"
description: "A buying guide for RAG retrieval: pgvector, Pinecone, Qdrant and Weaviate, what each is genuinely best at, the five questions that decide it, and the failure modes no vector database fixes."
canonical: https://past.dev/vector-database-for-rag
last-updated: 2026-08-26
---
# Vector database for RAG: how to choose one

Source: https://past.dev/vector-database-for-rag

Choose on operational constraints, not on a leaderboard. If you already run Postgres, start with pgvector and do not add a service. If you want a managed index and no infrastructure at all, Pinecone. If you want open source you can self-host with strong payload filtering, Qdrant. If you want keyword and vector search fused in one query, Weaviate. All four will retrieve the passage that resembles the question. None of them will tell you whether that passage is still true, and that is where most RAG systems actually fail.

## What a vector database does in a RAG pipeline

One job: given a query embedding, return the nearest stored embeddings, fast, with a filter applied. Everything else in a retrieval-augmented generation pipeline, the chunking, the embedding model, the reranker, the prompt and the model, sits outside it.

That matters when choosing, because the parts that most often decide answer quality are the parts the database does not own. Two teams on the same index, with different chunking and a different embedding model, get very different results.

## Best vector database for RAG: the four real options

Four cover almost every case. Two more are worth knowing about.

| Tool | Licence | How you run it | Reach for it when |
| --- | --- | --- | --- |
| [pgvector](https://github.com/pgvector/pgvector) | PostgreSQL licence | An extension in your own Postgres | You already run Postgres and want vectors in the same transaction and backup |
| [Pinecone](https://www.pinecone.io/) | Commercial, closed source | Fully managed only, no self-host | You want an index with no servers to operate and accept that data leaves your network |
| [Qdrant](https://qdrant.tech/) | Apache 2.0 | Self-host, or their managed cloud | You want open source, heavy metadata filtering and control over quantization |
| [Weaviate](https://weaviate.io/) | BSD 3-Clause | Self-host, or their managed cloud | You want BM25 and vector search fused in a single query, with vectorizer modules built in |
| [Milvus](https://milvus.io/) | Apache 2.0 | Self-host, distributed, or managed | You are past the point where one node holds the index |
| [Chroma](https://www.trychroma.com/) | Apache 2.0 | Embedded, or a server | You are prototyping and want the shortest path from a notebook to a retriever |

### pgvector, the default when you already run Postgres

pgvector adds a `vector` type to Postgres with both exact and approximate nearest neighbour search, and two index types, HNSW and IVFFlat. Its own documentation states the shape of the ceiling: vectors can carry up to 16,000 dimensions, and an index covers up to 2,000 of them for `vector`, 4,000 for `halfvec`. Common embedding models fit inside that.

What you get for free is everything Postgres already gives you: one transaction across your rows and your vectors, one backup, one access-control model, joins between an embedding and the record it belongs to. What you give up is the tuning surface a dedicated engine exposes, and the ability to scale the index separately from the rest of the database.

### Pinecone, the managed default

Pinecone is a hosted vector database with a serverless index model, and it is the option with the least operational surface: no nodes, no index rebuilds, no capacity planning. The trade is explicit. It is closed source and cannot be self-hosted, so your embeddings and metadata live in their account, which is a procurement question before it is a technical one.

### Qdrant, open source with strong filtering

Qdrant is written in Rust and released under Apache 2.0, self-hostable from a container or run as their cloud service. Its distinguishing feature in practice is filtering: payload conditions are applied during the search rather than as a pass afterwards, which is what keeps recall from collapsing when a query is scoped to one tenant or one user. Quantization options let you trade memory for recall deliberately.

### Weaviate, hybrid search in one server

Weaviate is written in Go and released under BSD 3-Clause. A single query can fuse BM25 keyword scoring with vector similarity, which matters more than it sounds: exact identifiers, error codes and product names are exactly what embeddings are worst at, and keyword scoring is what rescues them. Vectorizer modules can embed on insert, so the embedding step lives in the database rather than in your pipeline.

## Five questions that decide it

1. **Do you already run Postgres?** If yes, start with pgvector and only leave when you can name the limit you hit. A second datastore is a second thing to back up, secure and page someone about.
2. **Does every query filter by tenant, user or project?** Then filtering strategy matters more than raw nearest-neighbour speed. Ask whether filters are applied during the search or after it, because post-filtering an approximate result set is how a query returns three results out of a thousand matching documents.
3. **How big does the index get, honestly?** Millions of vectors fit on one node. Hundreds of millions do not, and that is the point where a distributed engine stops being over-engineering.
4. **Do your queries contain exact tokens?** Part numbers, error codes, names. Then you need keyword scoring alongside vectors, either built in or bolted on with a reranker.
5. **Who operates it at three in the morning?** For a team of three this outranks every other row in the table.

## Where RAG breaks, and it is not the database

Almost every retrieval failure worth debugging happens outside the vector store. These five account for most of them.

- **Chunking splits a fact from its subject.** The chunk says 40k and the name of the pilot is in the paragraph before it, so the retrieved passage is true and useless.
- **Embeddings match the topic, not the answer.** A question about a budget retrieves every paragraph that discusses budgets, ranked by how much they sound like budget talk.
- **Identity is not resolved.** The same person appears as a display name in a transcript, an email address in a thread and a handle in chat, so their history is three disconnected sets of chunks.
- **Nothing prefers the recent statement.** February's number and July's number are equally similar to the question, so the model receives both and picks one, silently.
- **The pipeline cannot abstain.** Top-k always returns k results, so a question the corpus cannot answer still arrives at the model with a confident-looking context.

Reranking helps the first two. The last three are not retrieval problems at all: they are questions about identity, time and evidence, which is the line between a retriever and a memory layer. [Vector database vs graph database vs memory](/vector-database-vs-memory) draws that line in full.

## When the problem is freshness, not storage

If your corpus is documentation, product pages or a manual, freshness is rarely the issue: the document is rewritten, the old version disappears, and retrieval is the whole job. Keep the vector database.

If your corpus is history, emails, meeting transcripts, tickets, CRM notes, then nothing is ever rewritten. Every statement stays true of the moment it was made, and the question you are asking is about now. That is the case past.dev is built for: send the text with the date it happened, ask a question later, get the current answer with the dated evidence behind it.

```bash
curl -X POST https://api.past.dev/api/v1/recall \
  -H "Authorization: Bearer $PAST_API_KEY" \
  -d '{ "query": "what is the Acme pilot budget?",
        "maxTokens": 1200 }'
```

`/recall` returns ranked evidence with its sources and no generated text, which is the shape a RAG pipeline already expects: merge it with your own retriever and keep your model, your prompt and your output contract. `/answer` goes one step further and returns a grounded answer, the evidence it used, its cost in dollars, and `abstained: true` when the evidence does not establish one. The [API reference](/docs/memory-api/api-reference) has both, and [how we measure memory](/benchmarks) has the harness.

## Frequently asked questions

### What is the best vector database for RAG?

There is no single best one. pgvector if you already run Postgres, Pinecone if you want zero operations, Qdrant if you want open source with strong filtering, Weaviate if you want keyword and vector search fused in one query, Milvus once the index outgrows a single node. The decision is almost always about operations and procurement rather than about recall.

### Is pgvector good enough for production RAG?

For most workloads, yes. It supports exact and approximate search with HNSW and IVFFlat indexes, and keeps vectors in the same database, transaction and backup as your rows. Move to a dedicated engine when you can name the constraint you hit: index size beyond one node, a filtering pattern that collapses recall, or a need to scale search independently of the rest of the database.

### Do I need a vector database for RAG at all?

Not always. Under a few thousand documents, keyword search or a plain SQL filter often retrieves as well and is far easier to debug. The case for vectors starts when queries are phrased differently from the source text and the corpus is too large to scan.

### Vector database vs RAG: are they the same thing?

No. RAG is the pattern of retrieving context at question time and putting it in the prompt. A vector database is one component that can serve the retrieval step, alongside keyword search, SQL and API calls.

### Can a memory API replace a vector database?

Only for the part of the corpus that is timestamped history. Documents you own, product content and anything static still belong in your own index. past.dev is built for the history where the answer changed, and `/recall` returns evidence in a form you can merge with the retriever you already have.

## Related

- [Vector database vs graph database vs memory](https://past.dev/vector-database-vs-memory)
- [What is agent memory?](https://past.dev/what-is-agent-memory)
- [Context engineering for AI agents](https://past.dev/context-engineering)
- [Memory API quickstart](https://past.dev/docs/memory-api/quickstart)
- [How we measure memory](https://past.dev/benchmarks)