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
Milvus scales each node type on shared object storage; pgvector lives inside one Postgres primary, with read-only hot-standby replicas for query fan-out.
Milvus scales each node type on shared object storage; pgvector lives inside one Postgres primary, with read-only hot-standby replicas for query fan-out.
Milvus and Zilliz Cloud adopters
  • Salesforce
  • Walmart
  • NVIDIA
  • eBay
  • IBM
  • Cisco
  • Roblox
  • Reddit
  • 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.
Tens of billionsvectors supported by Milvus DistributedView source
32,768dimensions per vector field in MilvusView source
40K+GitHub stars, milvus-io/milvusView source

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.

Published VectorDBBench results
MetricMilvusZilliz Cloudpgvector
Instance16 vCPU / 64 GB8 CU2 vCPU / 8 GB
Result seriesVectorDBBench v2VectorDBBench v2VectorDBBench v1 · 2023-07
Unfiltered: configurationMilvus-16c64g-sq4u-fp16-force_mergeZillizCloud-8cu-perfPgVector-2c8g (Jul 2023, IVF_FLAT, filter=0)
Unfiltered: QPS9,575.6913,316.2310.63
Unfiltered: P99 latency (ms)2.32.0730.7
Unfiltered: Recall0.91890.93830.8898
Filter keeps 1%: configurationMilvus-16c64g-sq8-partition_keyZillizCloud-8cu-perf-partition_keyPgVector-2c8g (Jul 2023, IVF_FLAT, filter=0.99)
Filter keeps 1%: QPS11,280.0810,020.5375.71
Filter keeps 1%: P99 latency (ms)1.62.6121.2
Filter keeps 1%: Recall0.95070.97880.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.

Milvus and pgvector capabilities and implementation choices
CapabilityMilvuspgvector
Index breadthHNSW 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 dimsHNSW and IVFFlat; vector indexable to 2,000 dims, halfvec to 4,000; binary quantization plus re-rank
Built-in BM25 hybrid searchBM25 function builds sparse vectors server-side; one hybrid_search call fuses dense and sparse with RRFRanker or WeightedRankertsvector plus a vector query, fused with RRF or a cross-encoder in SQL or application code
Function Chain rerankingDecay, 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 millionsPartition 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 tieringSegments and WAL in object storage; query nodes scale independently; tiered storage serves data far beyond node memory or diskHeap and index use Postgres storage; HNSW can run beyond cache, with additional I/O and latency.
Streaming ingestion while servingStreaming Node appends to a WAL and makes growing data queryable in real time while data nodes index sealed segmentsWrites and HNSW maintenance on the single primary
Scalar indexes and rich fieldsINVERTED, 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 hintFilter 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.

pgvector capabilities that come from Postgres, and the closest Milvus equivalent
CapabilitypgvectorMilvus
ACID transactionsRow, embedding and audit record in one transaction; roll back togetherPer-request consistency levels (Strong, Bounded, Session, Eventually); upserts not atomic across requests
JOINs with relational dataJOIN the vector table to users, orders and permissions in one statementNo cross-collection joins; join by primary key in the application
SQL and the Postgres toolboxViews, CTEs, triggers, EXPLAIN, pg_dump, point-in-time recoveryMilvusClient API and filter expressions; milvus-backup
Row-level securityCREATE POLICY per table covers SELECT, INSERT, UPDATE, DELETE; tenant isolation enforced in the databaseRBAC roles and privileges; tenant scoping through partition key and filters
One database, existing toolingCREATE EXTENSION vector on the Postgres you already run; any ORM or driver; managed on RDS, Aurora, Supabase, Neon, Cloud SQL, AlloyDB, AzureA 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.

Decision checklist: milvus or pgvector, question by question
QuestionLean pgvectorLean Milvus
How big will the vector table get?Fits one primary; HNSW index fits memoryHundreds of millions to tens of billions
How many tenants?Tens to thousands via partitioning or tablesMillions via partition key
How selective are the filters?Few broad filters; iterative scans sufficeHighly selective; scalar indexes pre-filter
Do you need BM25 hybrid search?tsvector plus RRF in SQL is enoughServer-side BM25, one hybrid_search call, Function Chain rerank
Who operates it?Existing Postgres team or managed PostgresZilliz 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.

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)

Zilliz Cloud is fully managed Milvus: the same engine and top-tier throughput, with no clusters to size, upgrade or scale.

Try Zilliz Cloud free