Skip to main content
Contents

10 best vector databases in 2026, compared

Pinecone, Milvus, Qdrant, Weaviate, Chroma, pgvector, MongoDB Atlas, Elasticsearch, OpenSearch and SereneDB, on what a RAG query needs after the nearest vectors

SereneDB TeamMaintainers
· 43 min read

The best vector database is the one that answers your whole query, and finding the nearest vectors is only the first part of it. A retrieval step for RAG or semantic search usually also has to filter on fields such as the tenant or the product, rank exact keywords like an error code or a function name, and sometimes count or group what it found. This post compares ten vector databases on those needs: Pinecone, Milvus, Qdrant, Weaviate, Chroma, pgvector, MongoDB Atlas Vector Search, Elasticsearch, OpenSearch and SereneDB.

We build SereneDB. Every claim about the other nine links to their own documentation, with the version it describes, and every claim about SereneDB links to ours and to a query you can run at the end of the post.

Available solutions reference​

DatabaseWhat it isFilter inside the vector searchBM25 + vectors in one querySQL with aggregatesIndexes your files and tables in placeLicense
PineconeVector database behind an HTTP APIYesPartly: RRF in SQL through pg_pineconePartly: SQL through pg_pineconeNoProprietary
MilvusOpen-source vector databaseYesYesPartly: aggregation API, no SQLPartly: Parquet, Lance, Vortex and IcebergApache 2.0
QdrantOpen-source vector search engineYesYesNoNoApache 2.0
WeaviateVector database with vectorizer modulesYesYesPartly: aggregation API, no SQLNoBSD-3-Clause core
ChromaEmbeddable retrieval databaseYesPartly: Chroma Cloud onlyNoNoApache 2.0
pgvectorVector extension for PostgreSQLAfter the index scanPartly: ts_rank, not BM25YesNoPostgreSQL
MongoDB Vector SearchVector stage in MongoDB pipelinesYesYesPartly: pipeline, no SQL vectorsNoSSPL v1
ElasticsearchLucene search engine with vector fieldsYesYesPartly: aggregations, no SQL vectorsNoAGPLv3, SSPL or ELv2 core; x-pack ELv2 only
OpenSearchLucene search engine with vector fieldsYesYesPartly: aggregations; experimental SQL vectors without GROUP BYNoApache 2.0
SereneDBSearch analytics database with Postgres SQLYesYesYesYesApache 2.0

How we compared them​

We compared the ten databases on ten questions. They come from what people search for next to "best vector database" and from what AI assistants look up when they answer it: hybrid BM25 search, metadata filtering and the license.

  1. Index types and quantization. Which approximate nearest neighbor (ANN) indexes it builds, such as HNSW or IVF, and how it compresses the vectors.
  2. Distance metrics. Cosine, Euclidean (L2), inner product and others.
  3. Filtering inside the vector search. Whether a filter on other fields is applied while the index is searched, or only to the results afterwards, when a selective filter can leave fewer than k rows.
  4. Keyword relevance next to the vectors. Whether it ranks full text with BM25 and can fuse that ranking with vector similarity, for example with reciprocal rank fusion (RRF), in one query.
  5. Query interface. SQL or its own API, and whether Postgres drivers work.
  6. Analytics over the hits. Whether the same query can group, count, sum or join the results.
  7. External sources. Whether it can index files you already have, such as Parquet or Iceberg on S3, or tables in another database, without a pipeline that copies them in first.
  8. Embeddings inside the database. Whether it can call an embedding model for you.
  9. License. Whether the engine is open source, and under which license.
  10. LangChain. Whether there is an integration for the framework most RAG tutorials start from.

The list below is grouped by architecture, not ranked: which database fits depends on what your query needs besides the nearest vectors. We don't rank by speed either, because speed depends on your vectors, your filters and the recall you need. Where we publish a benchmark, we link it with its method.

Every cell below comes from the vendors' documentation as we read it on 2026-11-05, for the versions listed under References; later releases may differ.

Vector database comparison table​

The figure sums up five columns of the available solutions reference; the three tables below give every cell with its source. A cell says "not documented" when the vendor's docs don't cover it.

A grid of the ten databases against five needs of one retrieval query: filter inside the vector search, BM25 and vectors in one query, SQL with aggregates, indexes your files and tables in place, and an open-source license. A full dot is documented, a half dot is partial, an empty ring is no or not documented. Pinecone: filter, partial BM25 with vectors, partial aggregates. Milvus: filter, BM25 with vectors, open-source license, partial aggregates and partial in-place files. Qdrant: filter, BM25 with vectors, open-source license. Weaviate: filter, BM25 with vectors, partial aggregates, partial license. Chroma: filter, partial BM25 with vectors, open-source license. pgvector: partial filter, partial BM25 with vectors, SQL with aggregates, open-source license. MongoDB Vector Search: filter, BM25 with vectors, partial aggregates. Elasticsearch: filter, BM25 with vectors, partial aggregates, partial license. OpenSearch: filter, BM25 with vectors, partial aggregates, open-source license. SereneDB: all five.A grid of the ten databases against five needs of one retrieval query: filter inside the vector search, BM25 and vectors in one query, SQL with aggregates, indexes your files and tables in place, and an open-source license. A full dot is documented, a half dot is partial, an empty ring is no or not documented. Pinecone: filter, partial BM25 with vectors, partial aggregates. Milvus: filter, BM25 with vectors, open-source license, partial aggregates and partial in-place files. Qdrant: filter, BM25 with vectors, open-source license. Weaviate: filter, BM25 with vectors, partial aggregates, partial license. Chroma: filter, partial BM25 with vectors, open-source license. pgvector: partial filter, partial BM25 with vectors, SQL with aggregates, open-source license. MongoDB Vector Search: filter, BM25 with vectors, partial aggregates. Elasticsearch: filter, BM25 with vectors, partial aggregates, partial license. OpenSearch: filter, BM25 with vectors, partial aggregates, open-source license. SereneDB: all five.

Indexes and filters​

DatabaseANN indexesQuantizationDistance metricsFilter during the search
PineconeIVF on dedicated read nodes, flat search for small indexes; not user-selectableRaBitQ in pg_pinecone's native engine; not named for the managed serviceCosine, dot product, EuclideanBefore ranking
MilvusFLAT, IVF, HNSW, DiskANN, AISAQ, ScaNN, GPU indexesScalar, product, RaBitQL2, inner product, cosine; Hamming, Jaccard, MinHash Jaccard for binary; BM25 for sparseBefore the ANN search
QdrantHNSW; exact on requestScalar, product, binary, TurboQuantDot, cosine, Euclidean, ManhattanWhile the graph is walked
WeaviateHNSW, flat, dynamic, HFreshProduct, binary, scalar, rotationalCosine, dot, L2 squared, Hamming, ManhattanBefore the HNSW search
ChromaHNSW; SPANN in distributed Chroma and Chroma Cloud4-bit RaBitQ, Chroma Cloud onlyL2, cosine, inner productBefore the search: only records that match the filter are queried
pgvectorHNSW, IVFFlatHalf precision, binaryL2, inner product, cosine, L1, Hamming, JaccardAfter the index scan, with iterative scans
MongoDB Vector SearchHNSW, flatScalar, binaryEuclidean, cosine, dot productBefore the graph is walked
ElasticsearchHNSW, flat, DiskBBQ; DiskBBQ with an Enterprise subscriptionint8, int4, BBQ; 2, 4 or 7 bits with DiskBBQL2, dot product, cosine, max inner productDuring the kNN search, with the filter in the knn clause
OpenSearchHNSW, IVF, flatScalar, product, binaryL2, L1, L∞, cosine, inner product, HammingDuring the kNN search, with the filter in the knn clause
SereneDBHNSW, IVF; exact on requestsq8 by default, sq4, fp16, bf16, pq, rabitq, bq and moreL2, cosine, inner product, L1Inside the index scan

Keywords, query language and analytics​

DatabaseBM25 + vectors in one queryQuery interfaceAggregates over the hits
PineconePartly: RRF in SQL through pg_pinecone; the API ranks by one scoring type per request, with RRF in the clientHTTP API and SDKs; SQL through pg_pineconeNone in the API; joins in SQL through pg_pinecone
MilvusYes: BM25 as sparse vectors, fused by RRF or weightsREST, gRPC and SDKs; no SQLBucketed count, sum, avg, min, max over the ANN candidates; exact group-by aggregates over filtered rows, without vector ranking
QdrantYes: BM25 as sparse vectors since 1.10, on full-text indexes since 1.20, fused by RRF or DBSFREST, gRPC and SDKs; no SQLGroups of hits; facet counts over filtered points
WeaviateYes: BM25F in a hybrid querygRPC client libraries and REST; no SQLAggregate API over search results, one group-by property
ChromaChroma Cloud only: BM25 sparse vectors fused with dense ones by RRFClient methods, in process in Python or over HTTP; no SQLNone; the Search API keeps the top k hits per group, Chroma Cloud only
pgvectorts_rank, not BM25; RRF written in SQLSQL over the Postgres protocolSQL: GROUP BY, joins
MongoDB Vector SearchYes: BM25 $search with $rankFusionAggregation pipeline from MongoDB drivers; its SQL Interface doesn't run vector searchgroup,group, lookup and other stages after $vectorSearch
ElasticsearchYes: BM25 and kNN fused by the RRF retriever with an Enterprise subscription, or by a score sum on the free licenseQuery DSL and ES|QL with KNNAggregations over kNN hits
OpenSearchYes: BM25 and kNN in a hybrid queryQuery DSL; SQL vectorSearch(), experimental, without GROUP BY over itAggregations over hybrid hits
SereneDBYes: BM25 and vectors fused with RRF in one SQL querySQL over the Postgres protocolSQL: GROUP BY, joins, window functions

External sources, embeddings and license​

DatabaseExternal sourcesEmbeddings insideLicenseLangChain
PineconeBulk import from object storageIntegrated embeddingProprietarylangchain-pinecone
MilvusParquet, Lance, Vortex and Iceberg on S3, GCS, Azure or OSS in external collections, with Storage V3 turned onEmbedding functions call providersApache 2.0langchain-milvus
QdrantNot documentedCloud Inference on Qdrant Cloud; BM25 only in the open-source serverApache 2.0langchain-qdrant
WeaviateNot documentedVectorizer modulesBSD-3-Clause core, three Enterprise features under the commercial Weaviate Licenselangchain-weaviate
ChromaChroma Sync copies files in from S3, GitHub or the web, Chroma Cloud onlyEmbedding functions, local default modelApache 2.0langchain-chroma
pgvectorForeign tables, scanned without an indexNot documentedPostgreSQL Licenselangchain-postgres
MongoDB Vector SearchCollections and views; federated S3 data can't be indexedAutomated Embedding, GA on Atlas, in preview on self-managed deploymentsSSPL v1langchain-mongodb
ElasticsearchIndexed first; ES|QL reads Parquet on S3 without kNN or BM25, experimental, with an Enterprise subscription when self-managedInference API, semantic_text, with an Enterprise subscriptionAGPLv3, SSPL v1 or ELv2 core; x-pack ELv2 onlylangchain-elasticsearch
OpenSearchIndexed first; S3 tables queried in place through Spark, without k-NN or BM25ML CommonsApache 2.0OpenSearch in langchain-community, archived in May 2026
SereneDBParquet, CSV, JSON and Iceberg on disk or S3; Postgres and ClickHouse tablesai_embedApache 2.0langchain-serenedb

The 10 vector databases, by architecture​

The list runs from engines built for vectors alone, through vector search added to a database or search engine you may already run, to one engine for the whole query. Each entry says what the database is, what its docs show it does well, when to pick it and what you run next to it for the rest of the query.

Vector-native engines with their own API. Five engines built around vector search, each queried through its own API and SDKs.

Pinecone​

Pinecone is a vector database you use through a versioned HTTP API and SDKs for Python, Node.js and Go. A document index holds dense vectors, sparse vectors, BM25-indexed text fields and filterable metadata side by side, and each search picks one of them to rank by. Facts below are for API version 2026-07 and pg_pinecone 0.11.0.

Pick it when your application already runs on Pinecone's API or SDKs.

What you run next to it: an API request commits to one scoring type, so a BM25 ranking and a vector ranking are fused in your application, as Pinecone's own RRF guide does, or in Postgres through pg_pinecone. Counts or sums over the hits need Postgres or another database, and data comes in by upsert or by bulk import from object storage. We compare the two in detail on SereneDB vs Pinecone.

Milvus​

Milvus is an open-source vector database under Apache 2.0. It stores dense, sparse and binary vectors next to scalar, JSON and text fields in typed collections, and you query it through SDKs for Python, Java, Go, Node.js, C++, C# and Rust or its REST and gRPC APIs. Facts below are for Milvus 3.0.5.

Pick it when your stack already runs on Milvus collections and its SDKs.

What you run next to it: Milvus has no SQL, so joins with your other tables happen elsewhere. Search aggregation works on the ANN candidates rather than on every match and can't be combined with a hybrid search in the same request; exact group-by aggregation runs on filtered rows without a vector ranking. Tables in another database are copied in first.

Qdrant​

Qdrant is an open-source vector search engine under Apache 2.0. It stores points, each with one or more vectors and a JSON payload, and you query them through one Query API over REST or gRPC, with SDKs for Python, TypeScript, Rust, Go, .NET and Java. Facts below are for Qdrant 1.20.0.

Pick it when your application already runs on Qdrant's Query API or one of its SDKs.

What you run next to it: Qdrant has no SQL. It groups hits by a field and counts filtered points with its Facet API, but sums and joins over the hits need another database, and data comes in by upsert or snapshot rather than being searched where it lives. We compare the two in detail on SereneDB vs Qdrant.

Weaviate​

Weaviate is a vector database that keeps objects with typed properties and one or more named vectors in collections. Its client libraries for Python, TypeScript, Go, Java and C# talk gRPC, and it can call an embedding model itself. The core engine is under BSD-3-Clause; since 1.40, released in October 2026, three Enterprise features sit under the separate, commercial Weaviate License and need a license key. Facts below are for Weaviate 1.40.3.

  • BM25F keyword search and vector search fused in one hybrid query, with relative-score or ranked fusion and an alpha weight.
  • Pre-filtering: the filter builds an allow-list before the HNSW search, with ACORN as the default strategy.
  • Vectorizer integrations embed objects on import and query text at search time.
  • The Aggregate API counts and sums the results of a vector or hybrid search, grouped by one property.

Pick it when your application already uses Weaviate's client libraries or its vectorizer modules.

What you run next to it: Weaviate has no SQL, so aggregates beyond what the Aggregate API returns, and joins with your other tables, happen elsewhere. Data comes in by batch import.

Chroma​

Chroma is an open-source retrieval database under Apache 2.0. It runs inside a Python process, in memory or on a local path, or as a server reached over HTTP, with clients for Python, TypeScript and Rust. Each record carries an embedding, metadata and a document text. Facts below are for Chroma 1.5.9.

Pick it when you are prototyping in Python and want vector search inside the process.

What you run next to it: single-node Chroma matches document text with substring and regex filters but doesn't rank it with BM25; hybrid search, sparse vectors and grouping come with Chroma's Search API, which is available in Chroma Cloud only. Counts and joins over the hits happen in your code.

Vector search inside a database or search engine you may already run. Four systems where vectors sit next to data you already keep there.

pgvector​

pgvector is an open-source PostgreSQL extension under the PostgreSQL License. It adds vector types, distance operators and HNSW and IVFFlat indexes, so embeddings sit in ordinary tables next to the rest of each row and you query them in plain SQL over any Postgres driver. Facts below are for pgvector 0.8.7.

Pick it when you already run PostgreSQL and the query is the nearest vectors plus filters and joins on tables you already have.

What you run next to it: PostgreSQL ranks full text with ts_rank and ts_rank_cd, not BM25, and pgvector's README fuses keyword and vector results by hand, with RRF written in SQL. With an approximate index the filter is applied after the index scan. Foreign tables can be scanned but not given a vector index, and core PostgreSQL has no Parquet or Iceberg reader.

MongoDB Vector Search​

MongoDB Vector Search, formerly Atlas Vector Search, adds approximate and exact nearest-neighbor search over embeddings in MongoDB documents. You define a vectorSearch index on a collection and query it with a $vectorSearch stage at the head of an aggregation pipeline. Facts below are for MongoDB 9.0.

  • Pre-filters on indexed fields, applied before the HNSW graph is walked.
  • BM25 keyword search in $search, fused with $vectorSearch by [rankFusion](https://www.mongodb.com/docs/manual/reference/operator/aggregation/rankfusion/)(RRF)or‘rankFusion](https://www.mongodb.com/docs/manual/reference/operator/aggregation/rankfusion/) (RRF) or `scoreFusion` in one pipeline.
  • Later pipeline stages such as $group and $lookup work on the hits.
  • Scalar and binary quantization, and Automated Embedding with Voyage AI models, generally available on Atlas and in preview on self-managed deployments.

Pick it when your documents already live in MongoDB.

What you run next to it: within one collection, little: keywords, vectors, filters and $group fit in one pipeline. What stays outside is SQL over the hits, since MongoDB's SQL Interface doesn't run vector search, and data that isn't in MongoDB yet: files on S3 and tables in another database are imported first. The server is under SSPL v1.

Elasticsearch​

Elasticsearch is a search and analytics engine built on Apache Lucene. It keeps JSON documents in indices, with vector fields next to text, keyword and numeric fields, and you query them over REST with JSON Query DSL or with ES|QL. Its core source is under a choice of AGPLv3, SSPL v1 or Elastic License 2.0; the x-pack features, ES|QL, the RRF retriever and the inference API among them, are under Elastic License 2.0 only. Facts below are for Elasticsearch 9.5.6.

  • A filter inside the knn clause is applied during the approximate search, so k matching documents come back.
  • BM25 is the default text scoring, and the RRF and linear retrievers fuse it with kNN in one request with an Enterprise subscription; on the free license a kNN search next to a query sums the two scores.
  • Aggregations run over the hits of a kNN query in the same request.
  • Float vectors are quantized to int8, int4 or one-bit BBQ, or to 2, 4 or 7 bits with DiskBBQ, and the inference API embeds text in the engine; DiskBBQ and the inference API need an Enterprise subscription.

Pick it when your documents are already indexed in Elasticsearch.

What you run next to it: for one index, little: keywords, vectors, filters and aggregations fit in one request. What stays outside is SQL over Postgres drivers, and data that isn't indexed yet: ES|QL can read Parquet on S3 in an experimental mode, which needs an Enterprise subscription when self-managed, but without kNN or BM25 over it, so files and tables elsewhere are ingested first. We compare the two in detail on SereneDB vs Elasticsearch.

OpenSearch​

OpenSearch is a search and analytics engine built on Apache Lucene, under Apache 2.0. It keeps JSON documents in indices, with vector fields next to text, keyword and numeric fields, and you query them over REST with JSON Query DSL; SQL runs k-NN queries through an experimental vectorSearch() function. Facts below are for OpenSearch 3.9.0.

Pick it when your documents are already indexed in OpenSearch.

What you run next to it: for one index, little: keywords, vectors, filters and aggregations fit in one request. What stays outside is SQL over Postgres drivers, and data that isn't indexed yet: OpenSearch can query S3 tables in place through Spark, but without k-NN or BM25 over them, so files and tables elsewhere are ingested first. We compare the two in detail on SereneDB vs OpenSearch.

One SQL engine for vectors, keywords and analytics. The last entry answers the whole query in one statement.

SereneDB​

SereneDB is a real-time search analytics database: one Postgres-compatible engine that answers hybrid questions, finding the relevant records in unstructured data and computing over them in the same query. It is open source under Apache 2.0. An embedding is a FLOAT[N] column, and its HNSW or IVF index is one more column of the same inverted index that serves full-text search and filters.

  • Indexes: HNSW and IVF, with l2, cosine, inner product and l1 distance and eleven quantizers from 16-bit floats down to one bit per dimension, sq8 by default.
  • Filters inside the search: a filter on an indexed column runs inside the index scan; EXPLAIN on a filtered top-k query shows the filter in the same IRESEARCH_SCAN as the cosine ranking.
  • Hybrid in one statement: BM25 and vector rankings fused with RRF in one SQL query.
  • Analytics over the hits: the hits are rows, so GROUP BY, joins and window functions apply to them.
  • External sources: full-text and vector indexes over Parquet, CSV, JSON and Iceberg files on disk or S3, and over tables in Postgres or ClickHouse, with the rows left where they are.
  • Postgres protocol: psql, psycopg, JDBC and other Postgres drivers connect as they are; embeddings come from SQL with ai_embed, and langchain-serenedb is a LangChain vector store.

Here is a retrieval step for a support assistant, over the articles table from Try it yourself: billing articles only, ranked by the keyword "refund" with BM25 and by closeness to the question's embedding, the two rankings fused with RRF.

SQL
WITH lex AS (
SELECT id, RANK() OVER (ORDER BY s DESC) AS rank FROM (
SELECT id, BM25(articles_idx.tableoid) AS s
FROM articles_idx
WHERE title @@ ts_phrase('refund') AND product @@ 'billing'
ORDER BY s DESC LIMIT 100) l
), vec AS (
SELECT id, RANK() OVER (ORDER BY d) AS rank FROM (
SELECT id, emb <=> [1.0, 0.0, 0.0]::FLOAT[3] AS d
FROM articles_idx
WHERE product @@ 'billing'
ORDER BY d LIMIT 100) v
), fused AS (
SELECT id, SUM(1.0 / (60 + rank)) AS rrf
FROM (SELECT * FROM lex UNION ALL SELECT * FROM vec) b
GROUP BY id
)
SELECT a.id, a.title, round(f.rrf, 4) AS rrf
FROM fused f JOIN articles a USING (id)
ORDER BY f.rrf DESC, a.id
LIMIT 3;
CODE
 id |                  title                   |  rrf
----+------------------------------------------+--------
1 | Refund a card payment | 0.0328
5 | Why a refund takes five days | 0.0325
2 | Change the billing address on an invoice | 0.0159

The same index answers the analytics question, how many articles mention a refund and how often they are read, per product:

SQL
SELECT product, count(*) AS articles, sum(views) AS views
FROM articles_idx
WHERE title @@ ts_phrase('refund')
GROUP BY product
ORDER BY views DESC;
CODE
 product | articles | views
---------+----------+-------
billing | 2 | 1800
orders | 1 | 950

Pick it when the query needs two or more of the nearest vectors, keyword relevance, filters and an aggregate; when the data already sits in Parquet, Iceberg or Postgres and you would rather index it than copy it; or when you want Apache 2.0 and the Postgres drivers you already use.

What you run next to it: nothing else for this query. The statement above is the whole retrieval step, with no second system for keywords and no export for the aggregate.

Speed, with the method: on VectorBench, published on 2026-11-05, SereneDB 26.11.1 answered faster than Qdrant 1.20.0 in 32 of the 33 result rows both engines reach over 247 million Cohere Wikipedia vectors, by 1.3× to 14×, with the same HNSW settings on the same hardware. Keyword ranking runs on IResearch, which you can compare with Lucene and Tantivy on the open Search Benchmark Game.

Also worth a look​

Three more engines that come up in the same answers:

  • LanceDB is a library that runs inside a Python, TypeScript or Rust application and stores tables in the open Lance columnar format; one hybrid query merges BM25 and vector results, with RRF by default. Its open-source edition is under Apache 2.0 (docs, version 0.41.0).
  • Vespa indexes tensor fields with HNSW, ranks text with BM25 as a rank feature and combines both in one YQL query through a rank profile; it is under Apache 2.0 (docs, version 8.781.11).
  • Redis indexes vectors in hashes or JSON documents with FLAT, HNSW or SVS-VAMANA, and FT.HYBRID fuses a BM25 text query with a vector query in one command; Redis 8 is under a choice of RSALv2, SSPL v1 or AGPLv3 (docs, version 8.10.3).

Dedicated vector database or vector search in the database you already run?​

Stay with a dedicated vector database when your application already runs on its API and the query needs nothing but the nearest vectors. Once the query also needs keyword relevance, filters on fields that live in your main database, or numbers computed over the hits, search in the engine that holds the data saves you a sync pipeline and one or two more systems.

Here's what a dedicated vector store asks of you in that case:

  • A copy of your data. Each embedding goes in with every field a filter will need, and the copy has to follow every insert, update and delete in the source, through change data capture, replication or a batch job.
  • A second system for keywords when its keyword ranking doesn't cover your queries, and a merge step in the application when the two rankings have to be combined.
  • A third system for numbers. Counting the hits by product or summing a metric over them means exporting the results to a database that can do it.
  • One permission model per system, each kept in step with the others.

Search in the engine that holds the data keeps one copy, one query language and one permission model. In SereneDB the data doesn't even have to move in first: an index can be built over the Parquet, CSV, JSON or Iceberg files you already have, or over a table in Postgres or ClickHouse, and CREATE SUBSCRIPTION applies a Postgres publication's inserts, updates and deletes to SereneDB tables, whatever indexes they carry. Our posts A demo trilogy: Vectorizer and Hybrid search and Search where your data lives walk through both.

How to choose a vector database (for RAG too)​

Start from what you already run and from what the query needs besides the nearest vectors:

  • Your application already calls a vendor's vector API. Stay with it, and add only what the query lacks.
  • You are prototyping in a Python notebook. An embedded engine such as Chroma or LanceDB runs inside the process, with nothing to set up.
  • You already run Postgres. pgvector adds vectors to your tables. When the same tables also need BM25 ranking, SereneDB speaks the Postgres protocol and can index a Postgres table where it is.
  • You already run Elasticsearch, OpenSearch or MongoDB. Their vector search sits next to the documents you already index.
  • The query needs the nearest vectors, keyword relevance and metadata filters at once, as most RAG retrieval does: pick an engine that fuses BM25 and vector rankings in one query. The comparison table shows which do.
  • It also counts or groups the hits, or the data sits in Parquet or Iceberg on S3. The table shows which engine answers that in one statement.
  • Open source is a requirement. See the license column.

Whatever you pick, test recall and latency on your own vectors and your own queries before you commit. Try it yourself below is a starting point for SereneDB.

How vector databases work​

A vector database stores embeddings, arrays of floats that a model computes from text, images or code so that similar items get nearby vectors, and finds the vectors nearest to a query vector. Comparing the query with every stored vector is exact but slow at millions of rows, so vector databases build an approximate nearest neighbor (ANN) index, which trades a little recall, the share of the true nearest neighbors a search returns, for speed.

Two index families dominate:

  • HNSW links every vector to its nearest neighbors in a layered graph. A query walks the graph from a coarse top layer down to the bottom one, keeping a beam of the best candidates. A wider beam raises recall and costs time.
  • IVF splits the vectors into clusters around centroids. A query compares itself with the centroids first, then scans only the vectors of the closest few clusters. Scanning more clusters raises recall and costs time.

Quantization stores each vector in fewer bits, from 16-bit floats down to one bit per dimension, so more of the index fits in memory. It costs some recall, which a second pass over the best candidates at full precision wins back.

Filtering is where vector databases differ most. A filter applied after the search can leave fewer than k results when it is selective; a filter applied during the search keeps walking until it finds k rows that pass. Keyword relevance is the other split: BM25 ranks exact terms such as an error code that embeddings tend to blur, which is why most RAG pipelines fuse the two rankings.

FAQ​

What are the top 10 vector databases?​

This post compares ten. Pinecone, Milvus, Qdrant, Weaviate and Chroma are built around vector search. pgvector, MongoDB Vector Search, Elasticsearch and OpenSearch add vector search to a database or search engine you may already run. SereneDB answers vectors, BM25 keywords, filters and SQL aggregates in one query. The comparison table shows what each one documents.

How do vector databases work?​

A vector database stores embeddings and finds the ones nearest to a query vector. Instead of comparing the query with every vector, it searches an approximate nearest neighbor index, usually an HNSW graph or IVF clusters, which trades a little recall for speed. Quantization shrinks the stored vectors, and filters narrow the search to rows that match other fields.

Which vector database is best for RAG?​

The one that retrieves by meaning and by exact keyword, with filters, in one query, because RAG questions mix both: "refund for order 4182" needs the embedding for the intent and the exact order number. Milvus, Qdrant, Weaviate, LanceDB, Vespa, Redis, MongoDB Vector Search, Elasticsearch, OpenSearch and SereneDB fuse BM25 and vector rankings in one query, and SereneDB also aggregates over the hits in the same SQL. Then pick by what you already run, and test recall on your own data.

What is the best open-source vector database?​

It depends on what else the query needs. Milvus, Qdrant, Chroma, LanceDB, Vespa and OpenSearch are under Apache 2.0, pgvector under the PostgreSQL License, Weaviate's core under BSD-3-Clause, and Elasticsearch's core and Redis 8 can be used under AGPLv3. When the same query also needs BM25 ranking, filters and aggregates over the hits, SereneDB, under Apache 2.0, answers it in one SQL statement.

Do I need a dedicated vector database, or can my SQL database do vector search?​

Not necessarily. pgvector adds HNSW and IVFFlat indexes to PostgreSQL, and SereneDB is a Postgres-compatible engine with HNSW and IVF next to BM25 and SQL analytics. A dedicated vector database fits when your application already runs on its API and the query needs only the nearest vectors. Once it also needs keywords, filters on your own tables or aggregates, search in the engine that holds the data saves a sync pipeline.

Which vector databases support hybrid search with BM25 and metadata filters?​

Per their docs on 2026-11-05, Milvus, Qdrant, Weaviate, LanceDB, Vespa, Redis, MongoDB Vector Search, Elasticsearch, OpenSearch and SereneDB fuse BM25 and vector rankings in one query and apply filters during the search. Pinecone's API ranks a request by BM25 or by vectors, not both, and pg_pinecone fuses the two with RRF in SQL. pgvector's hybrid search pairs PostgreSQL's ts_rank with RRF written in SQL. Single-node Chroma filters document text without ranking it, and hybrid search is in Chroma Cloud's Search API.

Try it yourself​

Start SereneDB in Docker and connect with psql, or any Postgres client:

BASH
docker run --rm -d --name serenedb -e SERENEDB_HOST_AUTH_METHOD=trust \
-p 127.0.0.1:7890:7890 serenedb/serenedb:26.11.2
psql -h 127.0.0.1 -p 7890 -U postgres

Create a table of support articles with a three-dimensional embedding, and one inverted index over its title (full text), its product (a filter) and its embedding (HNSW, cosine):

SQL
CREATE TABLE articles (
id INTEGER PRIMARY KEY,
title VARCHAR,
product VARCHAR,
views INTEGER,
emb FLOAT[3]
);

CREATE TEXT SEARCH DICTIONARY en AS
split_text(case := 'lower')
| normalize_tokens('en_US.UTF-8', accent := false)
| stem_words('en_US.UTF-8')
WITH (frequency, position);

CREATE INDEX articles_idx ON articles
USING inverted (id, title en, product, emb hnsw (metric = 'cosine'))
INCLUDE (views);

INSERT INTO articles VALUES
(1, 'Refund a card payment', 'billing', 1200, [0.90, 0.10, 0.00]),
(2, 'Change the billing address on an invoice', 'billing', 800, [0.60, 0.40, 0.00]),
(3, 'Request a refund for a cancelled order', 'orders', 950, [0.80, 0.20, 0.10]),
(4, 'Rotate an API key', 'security', 400, [0.00, 0.10, 0.90]),
(5, 'Why a refund takes five days', 'billing', 600, [0.85, 0.05, 0.10]),
(6, 'Export orders to CSV', 'orders', 300, [0.20, 0.80, 0.10]);

VACUUM (REFRESH_TABLE) articles;

Then run the hybrid query from the SereneDB entry and the aggregate after it. The last step indexes a Parquet file in place: it writes the table to a file, points a view at the file and builds the same kind of index over the view, so the rows stay in the file.

SQL
COPY (SELECT * FROM articles) TO '/tmp/articles.parquet' (FORMAT parquet);

CREATE VIEW lake AS
SELECT title, product, emb::FLOAT[3] AS emb
FROM read_parquet('/tmp/articles.parquet');

CREATE INDEX lake_idx ON lake
USING inverted (title en, product, emb hnsw (metric = 'cosine'));

SELECT title
FROM lake_idx
WHERE title @@ ts_phrase('refund')
ORDER BY emb <=> [1.0, 0.0, 0.0]::FLOAT[3]
LIMIT 2;
CODE
            title
------------------------------
Refund a card payment
Why a refund takes five days

A Parquet file stores the embedding as a variable-length list, so the view casts it to FLOAT[3], the fixed-size type a vector index needs. The same view works over s3:// paths and globs; see Indexing External Data.

Tested with SereneDB 26.11.2 on 2026-11-05.

References​

Vendor documentation read on 2026-11-05, for the versions below:

Interested in our product?

Join our community!

Questions, benchmarks and release chatter happen in the open.