Skip to content

Comparison

pgvector vs Qdrant vs Milvus vs seekdb: picking a vector store

Hosting model, index types, filtering, scale and licence for four vector stores, checked against primary documentation on 1 September 2026. Including the Ant Group engine that barely exists in English.

Last reviewed · 4 tools · 8 criteria

Verdict

If you already run Postgres and expect under roughly five million vectors, use pgvector and stop shopping. Choose Qdrant when metadata filtering is the hard part of your query, because its filterable HNSW builds filter-aware edges into the graph itself rather than bolting a predicate on afterwards. Choose Milvus when you genuinely have hundreds of millions of vectors, need GPU or on-disk indexes, and have someone who will own a Kubernetes deployment. seekdb is the interesting outsider: Apache 2.0, MySQL-compatible, runs embedded on one core and two gigabytes, and is worth a real evaluation for agent memory if you can read the Chinese documentation, which is where most of it lives.

Side by side

Criterion pgvector Qdrant Milvus seekdb
Hosting model Extension inside your existing Postgres. Offered by RDS, Cloud SQL, Supabase and Neon among others. No separate service.Self-hosted Apache 2.0 binary, or Qdrant Cloud with a free-forever node at 0.5 vCPU, 1GB RAM and 4GB disk. Hybrid Cloud and Private Cloud are quote-priced.Three modes: Lite (pip, Ubuntu 20.04+ and macOS 11+ only), Standalone (single Docker image), Distributed (Kubernetes). Managed as Zilliz Cloud.Embedded in-process, single-node server, or a client pointed at a remote OceanBase server. Documented to run on 1 CPU core and 2GB RAM.
Vector index types HNSW and IVFFlat only.HNSW only for dense vectors. Docs state Qdrant currently only uses HNSW as a dense vector index. Separate inverted index for sparse, returning exact results.FLAT, IVF_FLAT, IVF_SQ8, IVF_PQ, IVF_RABITQ, HNSW, HNSW_SQ, HNSW_PQ, HNSW_PRQ, SCANN, AISAQ, DiskANN on disk, GPU_CAGRA, GPU_IVF_FLAT, GPU_IVF_PQ, GPU_BRUTE_FORCE.HNSW and IVF with quantisation variants (Chinese README: HNSW 和 IVF 索引 及相关量化算法).
Filtering mechanism Ordinary SQL WHERE clauses over B-tree indexes, partial indexes or partitions. Iterative index scans since 0.8.0 via hnsw.iterative_scan and ivfflat.iterative_scan; hnsw.max_scan_tuples defaults to 20,000.Filterable HNSW adds graph edges derived from indexed payload values so filters apply during traversal. Payload indexes: keyword, integer, float, bool, geo, datetime, text, uuid, plus tenant and principal indexes. full_scan_threshold switches to brute force below a cardinality.Standard filtering narrows the set before ANN search. Iterative filtering, set with hints iterative_filter, applies scalars result by result for complex expressions. Scalar indexes: INVERTED, BITMAP, Trie, STL_SORT.Vector similarity, full-text and scalar predicates in one MySQL-compatible SQL statement, resolved by a multi-stage retrieval path.
Horizontal scale No native vector sharding. Vertical scale first, then read replicas or Citus. WAL-based replication and point-in-time recovery come from Postgres.Collections sharded across peers with Raft consensus for topology, replication_factor above 1 for fault tolerance. Live resharding shipped in v1.13.0 for Cloud, Hybrid Cloud and Private Cloud only; self-managed clusters fix shard_number at creation.Standalone guidance is up to roughly 100 million vectors. Distributed is documented from 100 million to tens of billions. 3.0.0 added Storage V3 manifest columnar storage on object storage, disabled by default.Single node by design. Scaling out means switching to a remote OceanBase server, so the distributed system you operate is OceanBase.
Licence PostgreSQL License, the permissive BSD-style text Postgres itself ships under. Latest release 0.8.6, 29 July 2026.Apache 2.0 for the engine in qdrant/qdrant. Cloud, Hybrid Cloud and Private Cloud control planes are commercial.Apache 2.0. Zilliz Cloud runs a proprietary search core called Cardinal that is not in the open repository.Apache 2.0 across oceanbase/seekdb and oceanbase/seekdb-develop.
Sparse vectors and hybrid search sparsevec type up to 16,000 non-zero elements, 1,000 of them indexable. Lexical search via Postgres tsvector, fused by you in SQL.Native sparse vectors since v1.7.0 with an exact inverted index, plus per-query IDF and server-side fusion in the Query API.SPARSE_INVERTED_INDEX and MINHASH_LSH, with 3.0.0 overhauling sparse via SINDI and Block-Max plus composable rerankers.Fusion of vector, full-text and scalar in a single query is the stated product thesis rather than an add-on.
Query interface SQL, with the <->, <=> and <#> distance operators. Every existing Postgres client and ORM works unchanged.REST and gRPC with official clients for Python, TypeScript, Rust, Go, Java and .NET. No SQL.gRPC through pymilvus and other SDKs plus a REST API. Filters are expression strings, not SQL.MySQL wire protocol and MySQL syntax. SQLAlchemy works, and any MySQL client is a client.
Dimension limits vector stores up to 16,000 dimensions but HNSW and IVFFlat index only 2,000. halfvec indexes 4,000, bit indexes 64,000, sparsevec indexes 1,000 non-zero elements.No hard dimension cap documented in the indexing pages checked on 1 September 2026.Not documented in the pages checked on 1 September 2026.Chinese README states vectors up to 16,000 dimensions (高达 16,000 维向量).

Which one to pick

  • pgvector

    You already operate Postgres, expect under roughly five million vectors, and your team writes SQL every day. The filter is a WHERE clause, backups are the ones you already take, and there is no new system on the on-call rota. Set hnsw.iterative_scan if selective filters return too few rows, and design around the 2,000-dimension index limit rather than the 16,000-dimension storage limit.

  • qdrant

    Filtering is the hard part of your query: multi-tenant isolation, time windows, or highly selective payload predicates where a naive post-filter destroys recall. Create your payload indexes before ingesting so the filter-aware HNSW edges get built. Accept that HNSW is the only dense index on offer, and if you self-host, pick your shard count at collection creation because live resharding is a Cloud feature.

  • milvus

    You have hundreds of millions of vectors or more, need GPU or on-disk indexes, and someone will own a Kubernetes deployment as their actual job. Also the right call when retrieval quality depends on choosing a specific quantisation for a fixed memory budget, since no other option here offers that index catalogue. Do not prototype on Milvus Lite and assume the feature set carries forward.

  • seekdb

    You want durable agent memory that speaks SQL, sits in-process or on one small node, and handles vector, full-text and scalar filters in one statement. Apache 2.0 with no field-of-use conditions, MySQL compatibility, and a 1 core plus 2GB footprint. Budget time for reading Chinese documentation, treat the published QPS figures as vendor claims, and understand that scaling out means adopting OceanBase.

A vector database decision usually arrives disguised as a benchmark question. Somebody circulates a recall-versus-QPS chart, everyone squints at it, and the constraint that will actually bite goes unexamined. That constraint is nearly always operational. Who runs this at three in the morning. What the licence permits when you resell the thing. Whether your filters are trivial or vicious. How much data you will have in eighteen months, and whether the migration path from here to there involves rewriting your query layer.

I picked four stores that are genuinely comparable, in the sense that all four will serve approximate nearest neighbour queries with metadata filters for a retrieval application. What they drag along differs enormously. pgvector is an extension inside a database you probably already operate. Qdrant is a dedicated Rust service. Milvus is a distributed system with a lakehouse story. seekdb is an Ant Group project from the OceanBase team that most English write-ups have described without reading the documentation, which is why I quote the Chinese README directly below.

Everything in the table comes from primary documentation checked on 1 September 2026. Where a vendor makes a performance claim I have labelled it as a vendor claim, because I have not run their benchmark and neither, in all likelihood, have you.

pgvector: the default you should have to argue your way out of

pgvector adds vector, halfvec, bit and sparsevec types to Postgres along with two index types, HNSW and IVFFlat. That is the whole surface area. The 0.8.6 release landed on 29 July 2026, and the licence is the PostgreSQL License, the same permissive BSD-style text Postgres itself ships under, which means no field-of-use conditions and no vendor with an incentive to change the terms later.

The dimension limits are the first thing that catches people. A vector column stores up to 16,000 dimensions but HNSW and IVFFlat only index up to 2,000 of them. Use halfvec and you index up to 4,000. Most embedding models sit comfortably inside that, though a few do not, and discovering it at index creation time rather than schema design time is a bad afternoon.

Filtering is where pgvector is both strongest and weakest. Strongest because a filter is just a WHERE clause, backed by ordinary B-tree indexes, partial indexes or table partitioning, and because your application developers already know how to write one. Weakest because a graph index and a selective predicate interact badly: the index walk can exhaust itself before finding enough rows that satisfy the filter. Version 0.8.0 addressed this with iterative index scans, enabled through hnsw.iterative_scan and ivfflat.iterative_scan, which keep searching until a threshold is reached. The HNSW threshold, hnsw.max_scan_tuples, defaults to 20,000. HNSW offers relaxed and strict ordering for those scans, strict guaranteeing results ordered by exact distance.

Horizontal scale is the honest limit. pgvector rides the write-ahead log, so replication and point-in-time recovery come free, but there is no native vector sharding. You scale up, then you add read replicas, then you reach for Citus. Teams that will cross a few hundred million vectors should plan the exit rather than discover it.

Qdrant: when the filter is the hard part

Qdrant is Apache 2.0 Rust, and its documentation is unusually direct about a limitation most vendors would bury. It supports exactly one dense index. The indexing page states that Qdrant currently only uses HNSW as a dense vector index. No IVF, no DiskANN, no GPU graph. If your workload needs a quantised on-disk index for a corpus that will not fit in memory, this is a real reason to look elsewhere, and I would rather say so than pretend index variety does not matter.

What Qdrant does better than the others is filtered search. Filterable HNSW extends the graph with additional edges derived from indexed payload values, so the filter participates in traversal instead of being applied to whatever the traversal happened to return. The operational catch matters: those filter-aware edges are only built for payload indexes that existed when the graph was constructed. Create a payload index after ingesting data and you have to rebuild the HNSW index for it to help. Payload index types cover keyword, integer, float, bool, geo, datetime, text and uuid, and there are dedicated tenant and principal indexes that lay out storage for multi-tenant and time-filtered access patterns. Below a cardinality set by full_scan_threshold the planner switches to brute force, which is the correct behaviour and one that surprises people reading latency graphs.

Sparse vectors arrived in v1.7.0 with an inverted index that returns exact rather than approximate results, and v1.19.0 added TurboQuant 4-bit as a primary storage datatype so you can keep only the quantised vectors and skip the originals on disk.

Distributed Qdrant shards collections across peers with Raft holding the topology, and a replication factor above one keeps a node failure from losing data. The sharp edge is resharding. It shipped in v1.13.0 but as a Cloud feature, covering Qdrant Cloud, Hybrid Cloud and Private Cloud. Self-managed operators still choose shard_number at collection creation and live with it, which is why the documentation advises at least two shards per node from the start.

Milvus: real scale, and what it costs you

Milvus is Apache 2.0 and has by far the widest index catalogue of the four. In memory there is FLAT, the IVF family including IVF_FLAT, IVF_SQ8, IVF_PQ and IVF_RABITQ, the graph family with HNSW, HNSW_SQ, HNSW_PQ and HNSW_PRQ, plus SCANN and AISAQ. On disk there is DiskANN. On GPU there is GPU_CAGRA alongside GPU_IVF_FLAT, GPU_IVF_PQ and GPU_BRUTE_FORCE. Scalar fields get INVERTED, BITMAP, Trie and STL_SORT. Nobody else here comes close, and if your retrieval quality genuinely depends on picking the right quantisation for a specific memory budget, this catalogue is the reason to be here.

Filtering has two modes. Standard filtering narrows the candidate set before the ANN search runs and is the default. Iterative filtering, activated with a hints parameter set to iterative_filter, walks results one at a time applying scalar predicates, which the docs recommend for complex expressions while warning that it gets slower as more entities need scalar evaluation.

Deployment is three products wearing one name, and the differences are larger than the marketing suggests. Milvus Lite is a pip install, but it supports FLAT as its only index type, has no partitions, no user and role management, no collection aliases, and runs on Ubuntu 20.04 or later and macOS 11 or later. Windows developers are not served. Standalone is one Docker image and the guidance puts it at up to roughly 100 million vectors. Distributed is Kubernetes and covers 100 million to tens of billions. Prototyping on Lite and deploying on Distributed means the feature surface changes underneath you.

Version 3.0.0 arrived on 29 July 2026 with Storage V3, a manifest-based columnar layout on object storage, and the ability to query Parquet, Lance, Iceberg and Vortex data in place rather than copying it. The 2.6 line is still shipping, 2.6.23 dated 28 August 2026. Two things deserve a plain statement. Storage V3 is disabled by default, so the headline feature is opt-in. And Zilliz Cloud, the managed service, runs a proprietary search core called Cardinal that is not in the open repository, which is precisely why managed-versus-self-hosted benchmark comparisons between the two are not comparing the same engine.

seekdb: the one nobody in English has read the docs for

OceanBase open-sourced seekdb at its annual conference in November 2025 under Apache 2.0, across both oceanbase/seekdb and oceanbase/seekdb-develop. The pitch is agent storage: vector, full-text, structured and semi-structured data in one engine, with vector similarity, full-text retrieval and scalar filters resolved in a single SQL statement through a multi-stage retrieval path.

The Chinese README is more specific than the English coverage. It names HNSW 和 IVF 索引 along with 相关量化算法, so both graph and inverted-file indexes with quantisation variants, and it documents vectors 高达 16,000 维. Deployment is 服务器部署模式 or 嵌入式部署模式, server or embedded, with server mode available through yum, Docker and desktop builds for Windows and macOS. The English README adds a third arrangement, pointing a client at a remote OceanBase server.

Two properties make it worth an afternoon. It is MySQL wire and syntax compatible, so SQLAlchemy and any MySQL client work without a new driver, and it runs on one CPU core and two gigabytes of memory, which the project demonstrates by running VectorDBBench at 1C2G. For an agent that needs durable memory next to its structured state, an embeddable engine that speaks SQL is a genuinely different shape from a separate vector service.

Now the honest part. The project publishes a claim of 1,523 QPS at 21.7ms P99 with roughly ten times the QPS of Milvus. That is a vendor benchmark on a vendor-chosen workload and I have not reproduced it, so treat it as a marketing figure until you run your own. seekdb also has no distributed story of its own. Scaling out means switching to a remote OceanBase server, so the cluster you end up operating is OceanBase, a much larger commitment than the pip install implies. And the documentation depth in English trails the Chinese by a wide margin, which is a maintenance risk if nobody on your team reads Chinese.

Recall benchmarks are the wrong tiebreaker

Published ANN benchmarks measure a system configured by the people who built it, on a dataset chosen by the people who published it, at a recall target somebody picked. All four of these can hit 95 percent recall on a standard corpus with the right parameters. The parameters are the product.

What actually decides the outcome in production is more mundane. Whether your filter selectivity collapses the graph walk. Whether the index fits in RAM at the quantisation you chose. Whether a schema change requires a reindex and how long that takes with writes still arriving. Whether backup and restore is a solved problem or a shell script somebody wrote once. Whether the person carrying the pager has operated this class of system before.

That last one dominates. A team fluent in Postgres will get better latency and far better uptime from pgvector at ten million vectors than from a Milvus cluster they are learning on. The chart says otherwise. The chart is not carrying the pager.

When none of these is the answer

Below roughly fifty thousand chunks, you do not have a vector database problem. A NumPy dot product over an in-memory matrix, or an in-process FAISS index rebuilt on deploy, will answer in single-digit milliseconds and costs nothing to operate. Teams reach for a database at this scale because it feels like the professional choice, then spend a quarter on infrastructure that a hundred lines would have covered.

If your retrieval quality problem is really a chunking or reranking problem, and it very often is, none of these four will fix it. Swapping the store while keeping 1,500-token chunks and no reranker changes the latency and not the answers.

If lexical matching carries most of your relevance, on product codes, names, or legal citations, a search engine built around BM25 with vectors added is a better fit than a vector engine with text bolted on. And if your embeddings need to sit under the same governance as the rest of your warehouse tables, evaluate the vector features already inside your analytical platform before adding a fifth system to the on-call rota.

Questions

Is pgvector fast enough for production, or is a dedicated vector database always better?

pgvector is fast enough for the overwhelming majority of retrieval workloads. The real ceiling is horizontal scale, since there is no native vector sharding: you go vertical, then read replicas, then Citus. A dedicated engine wins when you need index types pgvector does not have, such as DiskANN or a GPU graph, or when filter-aware graph traversal materially changes your recall. It rarely wins on raw latency at ten million vectors against a competently tuned Postgres.

Why does Qdrant only support HNSW when Milvus supports a dozen index types?

It is a deliberate scope decision, and the Qdrant docs say so plainly rather than hiding it. Effort has gone into making one graph index work well under filters, quantisation and multi-tenancy instead of maintaining many algorithms. That is a good trade if your problem is filtering and a bad one if you need an on-disk or GPU index for a corpus that will not fit in memory.

Is Milvus the same thing as Zilliz Cloud?

No, and the difference matters when reading benchmarks. Milvus is Apache 2.0 and uses the Knowhere engine. Zilliz Cloud runs Cardinal, a proprietary search core written by the same company but not published in the open repository. Performance figures comparing the managed service against self-hosted Milvus are comparing two different engines, not a hosting difference.

Is seekdb production ready?

It was open-sourced by the OceanBase team at their annual conference in November 2025, so it is young as an independent project even though the underlying storage lineage runs in large deployments. Apache 2.0, MySQL-compatible and genuinely small to run. The caveats are real: the depth of documentation is in Chinese, the published benchmark figures are vendor claims nobody independent has reproduced, and there is no distributed mode of its own.

How much should recall benchmarks influence the decision?

Less than most teams let them. All four can reach comparable recall on a standard corpus with the right parameters, so a published chart largely measures how well the publisher tuned each system. Filter selectivity, memory fit at your chosen quantisation, reindex time under live writes, backup and restore, and the operational experience of whoever carries the pager decide the outcome instead.

Sources

  1. pgvector repository README (index types, dimension limits, iterative scan parameters) github.com
  2. pgvector CHANGELOG (0.8.6 dated 29 July 2026) raw.githubusercontent.com
  3. pgvector LICENSE (PostgreSQL License) raw.githubusercontent.com
  4. PostgreSQL news: pgvector 0.8.0 released, introducing iterative index scans postgresql.org
  5. Qdrant documentation: Indexing (HNSW only for dense, payload index types, full_scan_threshold, sparse index, tenant and principal indexes) qdrant.tech
  6. Qdrant documentation: Distributed deployment (sharding, replication, Raft) qdrant.tech
  7. Qdrant v1.13.0 release notes (resharding, Cloud only) github.com
  8. Qdrant releases (v1.19.0, TurboQuant 4-bit primary storage) github.com
  9. Qdrant LICENSE (Apache 2.0) raw.githubusercontent.com
  10. Qdrant Cloud pricing (free tier specification) qdrant.tech
  11. Milvus documentation: Index explained (full index catalogue) milvus.io
  12. Milvus documentation: Filtered search (standard vs iterative filtering) milvus.io
  13. Milvus documentation: Milvus Lite (OS support and feature limitations) milvus.io
  14. Milvus 3.0.0 release notes (Storage V3, lakehouse external collections) github.com
  15. Milvus repository (Apache 2.0, deployment modes, scale statement) github.com
  16. Zilliz: Introducing Cardinal, the proprietary Zilliz Cloud search engine zilliz.com
  17. seekdb repository (Apache 2.0, deployment modes, HNSW, MySQL compatibility) github.com
  18. seekdb-develop Chinese README (HNSW 和 IVF 索引, 16,000 维向量, 1 核 CPU + 2GB 内存) github.com
  19. OceanBase press release: seekdb open-sourced at the 2025 annual conference prnewswire.com

Individual reviews: pgvector, Qdrant, Milvus, seekdb. All comparisons, or the full tool catalogue.