Milvus vs pgvector: a vector database comparison for growing data
Milvus gives production vector search three dedicated advantages: specialized indexes and server-side hybrid retrieval, independently scalable ingestion/indexing/query resources, and tiered storage for hot and cold data. As the corpus grows, prioritize query-node memory and local disk for the active working set while retaining historical data in object storage. Keep Postgres for transactions, joins and business records; use Milvus to scale retrieval.
- Apache-2.0 · GitHub 40K+ stars
- Dedicated vector and hybrid retrieval
- Scale query, ingestion and indexing separately
- Hot/cold tiers · durable object storage
- Salesforce
- Walmart
- NVIDIA
- eBay
- IBM
- Cisco
- Roblox
- Exa.ai
- OpenEvidence
- Read.ai
- Plaud
- Filevine
Milvus vs pgvector scalability: what happens when the table outgrows one Postgres box?
Milvus is built on storage-compute separation: segments and the write-ahead log live in object storage, a new query node loads its assigned segments instead of copying a disk, and ingestion, search and indexing scale on separate node types. Tiered storage lets a node serve data far beyond its memory.
pgvector scalability is Postgres scalability: scale up one instance, add hot-standby replicas (full copies, strictly read-only), or shard with Citus or PgDog, per the README. Every write and HNSW build runs on the primary. The documented behaviours:
- HNSW build time and memory: fast while the graph fits maintenance_work_mem; past that Postgres warns "hnsw graph no longer fits into maintenance_work_mem" and builds take significantly longer. Parallel builds (0.6.0+) default to 2 workers; a 1M x 1,536-dim build took 60.10 min and 7,734 MB on r7gd.16xlarge (Jonathan Katz, 2023).
- Indexable dimensions: vector up to 2,000, halfvec up to 4,000, bit up to 64,000.
- Post-filtering recall cliff: at the default hnsw.ef_search of 40, a WHERE matching 10% of rows returns about 4 rows; iterative index scans (0.8.0+) rescan until k rows are found, up to hnsw.max_scan_tuples (20,000).
- Index size vs memory: the README says indexes perform better in memory; AWS writes that an HNSW index must stay memory-resident or latency degrades.
Hot/cold separation: size retrieval resources for the active working set
Milvus Tiered Storage (2.6.4+) separates QueryNode caching from loading. Durable data stays in object storage; field chunks and segment indexes load on demand. Infrequently used cache entries can be evicted, while important fields and indexes can be warmed up.
For growing knowledge bases, historical documents and agent memory, this helps separate corpus capacity from active serving resources and reduce cold-data cache residency. pgvector also uses Postgres caching and disk-backed indexes; Milvus adds an object-storage-backed tiering mechanism designed for distributed vector retrieval.
- Keep historical data searchable without keeping every field permanently resident on QueryNodes.
- Scale query resources for traffic; size object storage and active cache for corpus growth.
Cold accesses can add latency. Warm critical data or use full-load mode for strict latency targets. Savings depend on access patterns, indexes, cache hit rates and query requirements.
Milvus, Zilliz Cloud and pgvector performance
Cohere 1M, 768 dimensions. Published results for unfiltered search and filtered search retaining 1% of the data.
| Metric | Milvus | Zilliz Cloud | pgvector |
|---|---|---|---|
| Instance | 16 vCPU / 64 GB | 8 CU | 2 vCPU / 8 GB |
| Result series | VectorDBBench v2 | VectorDBBench v2 | VectorDBBench v1 · 2023-07 |
| Unfiltered: configuration | Milvus-16c64g-sq4u-fp16-force_merge | ZillizCloud-8cu-perf | PgVector-2c8g (Jul 2023, IVF_FLAT, filter=0) |
| Unfiltered: QPS | 9,575.69 | 13,316.23 | 10.63 |
| Unfiltered: P99 latency (ms) | 2.3 | 2.0 | 730.7 |
| Unfiltered: Recall | 0.9189 | 0.9383 | 0.8898 |
| Filter keeps 1%: configuration | Milvus-16c64g-sq8-partition_key | ZillizCloud-8cu-perf-partition_key | PgVector-2c8g (Jul 2023, IVF_FLAT, filter=0.99) |
| Filter keeps 1%: QPS | 11,280.08 | 10,020.53 | 75.71 |
| Filter keeps 1%: P99 latency (ms) | 1.6 | 2.6 | 121.2 |
| Filter keeps 1%: Recall | 0.9507 | 0.9788 | 0.9999 |
Instances, indexes and test periods differ; these are published results, not a controlled comparison. pgvector uses the July 2023 IVFFlat run and serial P99 latency. Original sources are linked below.
Why choose Milvus for production retrieval
Milvus combines specialized retrieval, independent scaling and hot/cold tiering in one service. Allocate resources by query, ingestion and indexing demand, and manage cache by access patterns. These controls matter when retrieval becomes a growing production workload rather than a small addition to an existing database.
| Capability | Milvus | pgvector |
|---|---|---|
| Index breadth | HNSW with SQ, PQ, PRQ; IVF_FLAT, IVF_SQ8, IVF_PQ, IVF_RABITQ; SCANN; DiskANN for data exceeding RAM; GPU_CAGRA, GPU_IVF; up to 32,768 dims | HNSW and IVFFlat; vector indexable to 2,000 dims, halfvec to 4,000; binary quantization plus re-rank |
| Built-in BM25 hybrid search | BM25 function builds sparse vectors server-side; one hybrid_search call fuses dense and sparse with RRFRanker or WeightedRanker | tsvector plus a vector query, fused with RRF or a cross-encoder in SQL or application code |
| Function Chain reranking | Decay, Model (TEI, vLLM, Cohere, Voyage) and Boost rankers run server-side; Function Chain in hybrid search on Milvus 3.0+ | Rerank in application code |
| Multi-tenancy at millions | Partition keys prune the search scope; include the correct tenant filter on every request. Database, collection and partition are other tenant layouts. | List partitioning or a table per tenant |
| Storage-compute separation and hot/cold tiering | Segments and WAL in object storage; query nodes scale independently; tiered storage serves data far beyond node memory or disk | Heap and index use Postgres storage; HNSW can run beyond cache, with additional I/O and latency. |
| Streaming ingestion while serving | Streaming Node appends to a WAL and makes growing data queryable in real time while data nodes index sealed segments | Writes and HNSW maintenance on the single primary |
| Scalar indexes and rich fields | INVERTED, BITMAP, STL_SORT, Trie, JSON path indexes on VARCHAR, JSON, ARRAY, TEXT (Milvus 3.0+), TIMESTAMPTZ; filter runs before the ANN search, or via the iterative_filter hint | Filter applies after the index scan; iterative_scan rescans up to hnsw.max_scan_tuples |
What pgvector gives you that Milvus doesn't
pgvector's advantage is not the vector index; it is everything Postgres already does around the vector column. For a team whose data lives in Postgres these are reasons to stay, and a Milvus vs Postgres decision starts here.
| Capability | pgvector | Milvus |
|---|---|---|
| ACID transactions | Row, embedding and audit record in one transaction; roll back together | Per-request consistency levels (Strong, Bounded, Session, Eventually); upserts not atomic across requests |
| JOINs with relational data | JOIN the vector table to users, orders and permissions in one statement | No cross-collection joins; join by primary key in the application |
| SQL and the Postgres toolbox | Views, CTEs, triggers, EXPLAIN, pg_dump, point-in-time recovery | MilvusClient API and filter expressions; milvus-backup |
| Row-level security | CREATE POLICY per table covers SELECT, INSERT, UPDATE, DELETE; tenant isolation enforced in the database | RBAC roles and privileges; tenant scoping through partition key and filters |
| One database, existing tooling | CREATE EXTENSION vector on the Postgres you already run; any ORM or driver; managed on RDS, Aurora, Supabase, Neon, Cloud SQL, AlloyDB, Azure | A separate service (Milvus Lite, Standalone or Kubernetes) with its own SDKs |
When is pgvector the better choice, and when Milvus? A decision checklist
pgvector is a well-maintained extension, and keeping vectors inside the database you already run is a real advantage. Is pgvector good enough for production RAG? For a single-tenant corpus on an existing Postgres, yes: it fits when the vector table fits one primary and you need transactions, JOINs or row-level security between embeddings and relational rows; agent memory with transactional updates is a good example, paired with Milvus for the large retrieval corpus. Teams searching for pgvector alternatives are usually hitting the single-primary behaviours above.
| Question | Lean pgvector | Lean Milvus |
|---|---|---|
| How big will the vector table get? | Fits one primary; HNSW index fits memory | Hundreds of millions to tens of billions |
| How many tenants? | Tens to thousands via partitioning or tables | Millions via partition key |
| How selective are the filters? | Few broad filters; iterative scans suffice | Highly selective; scalar indexes pre-filter |
| Do you need BM25 hybrid search? | tsvector plus RRF in SQL is enough | Server-side BM25, one hybrid_search call, Function Chain rerank |
| Who operates it? | Existing Postgres team or managed Postgres | Zilliz Cloud, or Kubernetes with Milvus Operator |
Which AI companies and enterprises run Milvus in production?
Milvus and Zilliz Cloud (managed Milvus) run in AI-native companies and large enterprises alike: the milvus.io adopter wall includes Salesforce, Walmart, NVIDIA, eBay, IBM, Cisco, Roblox and Reddit, alongside Exa.ai, OpenEvidence, Read.ai, Plaud and Filevine.
- OpenEvidence: under 10 ms search latency and 4,000 QPS at peak on Zilliz Cloud.
- Plaud: 10B+ vector chunks per region with under 200 ms average recall latency.
- Exa: neural search latency cut from seconds to under 200 ms with hybrid search.
Explore the concepts
Frequently asked questions
Is Milvus faster than pgvector?
The table lists published results for all three systems, but instances, indexes and test periods differ. It does not establish a same-condition speed ratio. Benchmark with matching data, hardware, filters and recall targets.
Can pgvector handle 100 million vectors?
The README sets no row limit; capacity is the primary's. AWS published a 367 GB HNSW index for LAION 100M (768 dims), built in 16.1 hours, serving 3.4 QPS cold on a 128 GB cache. Milvus Standalone is documented to about 100 million vectors, Distributed to tens of billions.
Does pgvector support hybrid search?
Yes: combine a vector query with Postgres full-text search (tsvector) and fuse results with Reciprocal Rank Fusion or a cross-encoder. Milvus runs BM25 server-side and fuses dense and sparse results in one hybrid_search call.
When should I use pgvector instead of Milvus?
When the vectors sit next to relational rows you join and update transactionally, the table fits one Postgres instance, and you want row-level security and SQL from one database. pgvector limitations (2,000 indexed dims, maintenance_work_mem-bound builds, full-copy replicas) decide the switch.
How hard is migrating from pgvector to Milvus later?
It is a copy. VTS ships a Postgres Vector source with a pg_to_milvus config, so embeddings and columns move without re-embedding. Map columns to scalar or JSON fields, build indexes, dual-write from the same source, and keep relational tables in Postgres.
Sources and technical documentation (73)
- https://milvus.io
- https://github.com/milvus-io/milvus
- https://milvus.io/docs/architecture_overview.md
- https://milvus.io/docs/install-overview.md
- https://milvus.io/docs/scaleout.md
- https://milvus.io/docs/tiered-storage-overview.md
- https://milvus.io/docs/index-explained.md
- https://milvus.io/docs/ivf-rabitq.md
- https://milvus.io/docs/diskann.md
- https://milvus.io/docs/gpu_index.md
- https://milvus.io/docs/limitations.md
- https://milvus.io/docs/schema.md
- https://milvus.io/docs/text.md
- https://milvus.io/docs/use-json-fields.md
- https://milvus.io/docs/index-scalar-fields.md
- https://milvus.io/docs/filtered-search.md
- https://milvus.io/docs/use-partition-key.md
- https://milvus.io/docs/multi_tenancy.md
- https://milvus.io/docs/full-text-search.md
- https://milvus.io/docs/multi-vector-search.md
- https://milvus.io/docs/reranking.md
- https://milvus.io/docs/decay-ranker-overview.md
- https://milvus.io/docs/model-ranker-overview.md
- https://milvus.io/docs/boost-ranker.md
- https://milvus.io/docs/release_notes.md
- https://milvus.io/docs/embedding-function-overview.md
- https://milvus.io/docs/consistency.md
- https://milvus.io/docs/upsert-entities.md
- https://milvus.io/docs/rbac.md
- https://milvus.io/docs/quickstart.md
- https://milvus.io/docs/install_standalone-docker.md
- https://milvus.io/docs/integrations_overview.md
- https://github.com/zilliztech/milvus-backup
- https://github.com/zilliztech/vts
- https://github.com/zilliztech/vts/blob/master/seatunnel-examples/seatunnel-engine-examples/src/main/resources/examples/pg_to_milvus.conf
- https://github.com/pgvector/pgvector
- https://github.com/pgvector/pgvector/blob/master/CHANGELOG.md
- https://github.com/pgvector/pgvector/blob/master/LICENSE
- https://www.postgresql.org/docs/current/high-availability.html
- https://www.postgresql.org/docs/current/hot-standby.html
- https://www.postgresql.org/docs/current/ddl-rowsecurity.html
- https://docs.aws.amazon.com/AmazonRDS/latest/PostgreSQLReleaseNotes/postgresql-extensions.html
- https://supabase.com/docs/guides/database/extensions/pgvector
- https://neon.com/docs/extensions/pgvector
- https://docs.cloud.google.com/sql/docs/postgres/extensions
- https://docs.cloud.google.com/alloydb/docs/reference/extensions
- https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/how-to-use-pgvector
- https://zilliz.com/vdbbench-leaderboard
- https://github.com/zilliztech/VectorDBBench
- https://github.com/zilliztech/VectorDBBench/blob/main/vectordb_bench/results/leaderboard_v2.json
- https://github.com/zilliztech/VectorDBBench/blob/main/vectordb_bench/results/PgVector/result_20230727_standard_pgvector.json
- https://github.com/zilliztech/VectorDBBench/tree/main/vectordb_bench/backend/clients
- https://jkatz05.com/post/postgres/pgvector-hnsw-performance/
- https://aws.amazon.com/blogs/database/accelerate-hnsw-indexing-and-searching-with-pgvector-on-amazon-aurora-postgresql-compatible-edition-and-amazon-rds-for-postgresql/
- https://supabase.com/blog/pgvector-vs-pinecone
- https://supabase.com/blog/increase-performance-pgvector-hnsw
- https://supabase.com/blog/pgvector-fast-builds
- https://www.tigerdata.com/blog/pgvector-is-now-as-fast-as-pinecone-at-75-less-cost
- https://www.tigerdata.com/blog/pgvector-vs-pinecone
- https://aws.amazon.com/blogs/database/supercharging-vector-search-performance-and-relevance-with-pgvector-0-8-0-on-amazon-aurora-postgresql/
- https://aws.amazon.com/blogs/database/scale-pgvector-with-binary-quantization-on-amazon-aurora-postgresql/
- https://aws.amazon.com/blogs/database/running-pgvector-in-production-on-amazon-aurora-postgresql/
- https://arxiv.org/abs/2603.23710
- https://docs.langchain.com/oss/python/integrations/vectorstores/pgvector
- https://docs.langchain.com/oss/python/integrations/vectorstores/milvus
- https://zilliz.com/customers/filevine
- https://zilliz.com/customers/openevidence
- https://zilliz.com/customers/exa
- https://zilliz.com/customers/airtable
- https://zilliz.com/customers/plaud
- https://zilliz.com/customers/read-ai
- https://zilliz.com/customers/meituan
- https://lfaidata.foundation/projects/