The question every retrieval project reaches
Every retrieval system reaches the same afternoon: the documents are chunked, the embeddings are computed, and someone has to decide where the vectors live. The three names that come up are Qdrant, Weaviate and Milvus, and the comparison below rests on two kinds of evidence that should be kept apart. Qdrant runs under this site's search and under the Second Brain pattern, in production since 2024, so what I say about it is witness. Weaviate and Milvus I have run only to evaluate them, so what I say about those two comes from their documentation, their published benchmarks and the shape of their deployments, and a reader should weigh it accordingly.
Five things worth comparing
The dimensions that decide a deployment are not the ones on the benchmark charts. Query latency matters, but so does how many processes a Tuesday-morning restart involves, whether the filtering you need is a first-class feature or a workaround, what it costs to move away later, and whether one engineer can run the thing without a second one on call. The synthetic benchmarks are easy to find and mostly agree with each other; the operational questions are where the three separate.
Qdrant, the one I run
Qdrant is written in Rust, ships as a single binary or one container, and has needed nothing from me since the day it went in. The published p99 latencies sit in the low single-digit milliseconds for collections under a few hundred million vectors, which matches what I see on a store far smaller than that, and the operational surface is small enough that the whole configuration fits in a file I can read at a glance. Its distinguishing strength is filtering: named vectors and payload filters are part of the query rather than a post-processing step, so a retrieval that must be scoped to a tenant, a date range or a document type before the similarity search runs does not pay for the unscoped search first. For the retrieval systems I build, where a client's documents must never leak across a workspace boundary, that is the feature that decides it.
Weaviate, when the data is not just text
Weaviate's case is multi-modal search. Where a query has to span text, images and structured fields at once, its module system and GraphQL interface do the joining that would otherwise be application code, and that is a real capability rather than a brochure one. The price is moving parts. It is a Go service with more configuration than Qdrant, its documentation quotes latencies of roughly eight to fifteen milliseconds in production-shaped setups, and the GraphQL surface is expressive in the way that makes the third developer on a project reach for the manual. For most retrieval over documents it is more database than the job needs.
Milvus, when the vectors are counted in billions
Milvus is built for scale that almost nobody reading this has: billions of vectors, GPU-accelerated indexes, a distributed cluster. Its performance ceiling is the highest of the three and its own benchmarks show it, but the architecture that gets there is etcd for metadata, MinIO for objects and Pulsar for the log, which makes a multi-node deployment the default rather than the exception. A team with dedicated infrastructure engineers can run that. A team of one, or a client whose compliance team wants to understand every process on the box, should not start there.
The Verdict
Choose Qdrant for self-hosted retrieval under a few hundred million vectors, especially where filtering by tenant or document type is part of every query; it is what I run and what I would install for a client on Monday. Choose Weaviate when the search is genuinely multi-modal and the team can carry the extra surface. Choose Milvus when the collection is measured in billions and someone is paid to operate a cluster. For most teams the first answer is the right one. The scale that justifies the other two arrives later, if it arrives at all.
The retrieval stack I run, with the diagrams, is on the open-source stack page.