# Vector Databases Compared: Qdrant, Weaviate and Milvus

> Vector database for RAG and search: how Qdrant, Weaviate and Milvus differ and which to run on a VDS.

A vector database is useful where a plain `WHERE title LIKE '%...%'` cannot find meaning — only exact letter matches. An embedding turns text, an image, or audio into a vector of numbers, and a vector database quickly finds records with a close meaning among millions. The three most common candidates for a VDS are Qdrant, Weaviate, and Milvus. Let's see how they differ in practice and which one fits your case.

## What is a vector database and why use one

A classic index looks for an exact substring. A vector index looks for the nearest points in a multi-dimensional space using a distance metric — cosine similarity or Euclidean distance. The query is also turned into a vector by the same embedding model, and the database returns the top-k nearest records in milliseconds even across tens of millions of vectors.

This kind of search powers [RAG systems](https://www.zevshost.net/en/kb/rag-sistema-nastroika/), recommendations, deduplication, and similar-image search. The choice of a specific database affects RAM usage, write speed, and how hard it is to run on your own server.

## Qdrant: simplicity and a low entry bar

Qdrant is written in Rust, ships as a single binary or a Docker container, and needs no external dependencies like ZooKeeper or etcd. It stores vectors together with payload fields and supports filtering by metadata right during the search, not after it.

```
docker run -d --name qdrant \
  -p 6333:6333 -p 6334:6334 \
  -v /opt/qdrant/storage:/qdrant/storage \
  qdrant/qdrant:latest
```

On a VDS with 4 GB of RAM, Qdrant comfortably holds a collection of a couple million vectors with dimension 768. Detailed setup is covered in the article on [setting up Qdrant on a VPS](https://www.zevshost.net/en/kb/qdrant-nastroika-vps/).

## Weaviate: modules and built-in vectorization

Weaviate is written in Go and adds a module layer: you can plug in text vectorization through an external API right inside the database, without routing data through a separate embedding service. The data schema is built through classes with typed properties, which is handy when a record has many attributes besides the vector.

On the downside, Weaviate is more demanding on memory with a large number of classes and relies more on the GraphQL interface, which you will need to learn separately from the usual REST.

## Milvus: scaling for heavy workloads

Milvus is built for tens and hundreds of millions of vectors and a distributed architecture: separate nodes for ingesting writes, indexing, and queries. This design pays off on a cluster of several servers, but on a single VDS it adds overhead — Milvus in docker-compose brings up etcd and MinIO as mandatory dependencies.

```
wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml -O docker-compose.yml
docker compose up -d
```

Milvus standalone mode removes some of the complexity, but it still consumes more idle RAM than Qdrant or Weaviate on the same task.

## Comparison by key parameters

| Parameter | Qdrant | Weaviate | Milvus |
| --- | --- | --- | --- |
| Implementation language | Rust | Go | Go + C++ |
| Dependencies to start | none | none | etcd, MinIO |
| Idle RAM | from 200 MB | from 400 MB | from 1.5 GB |
| Payload filtering | yes, built-in | yes, via classes | yes, via schema |
| Best fit | single server, RAG | complex data schema | cluster, hundreds of millions of vectors |

## What to run on your VDS

For a chatbot with a knowledge base, product catalog search, or a personal project on a VDS with 4-8 GB of RAM, the sensible choice is Qdrant: minimal moving parts, one process, a clear REST API. If your data is already structured as objects with many related properties and you want built-in vectorization, pick Weaviate. Milvus only makes sense with a clear plan to grow to a cluster and tens of millions of records — otherwise its etcd and MinIO will simply eat resources for nothing.

As an alternative without a separate service, consider [pgvector in PostgreSQL](https://www.zevshost.net/en/kb/pgvector-postgresql/) if your project already runs that database and the load stays under a couple million records.

- Up to 2-5 million vectors, a single server — Qdrant.
- A complex object schema, built-in vectorization needed — Weaviate.
- A cluster, tens to hundreds of millions of vectors — Milvus.
- The project already runs PostgreSQL, load is small — pgvector instead of a separate database.

## Checklist before you choose

Before deploying any of these databases, assess three things: how many vectors you will have in a year, how much free RAM the server has, and whether you need metadata filtering on every query. A mistake at this step costs more than migrating data between databases — vector formats differ between them, and you will have to run the embeddings again from scratch.

- Estimate the expected number of vectors and their dimension.
- Check free RAM: Milvus without a memory margin will crash with OOM.
- Decide whether you need field filtering together with vector search.
- Start with Qdrant if in doubt — migrating to a heavier solution later is easier than rolling back from one.

## Frequently asked questions

### Can data be migrated between Qdrant, Weaviate, and Milvus later if the initial choice turns out wrong?

There's no built-in way to move data directly between these databases, since each stores vectors and indexes in its own internal format. Migration effectively means running every object back through the same embedding model and loading the resulting vectors into the new database through its API, rather than copying files — worth factoring into the decision up front.

### How does vector search relate to full-text search — does one replace the other?

Full-text and vector search solve different problems and usually complement rather than replace each other: full-text finds exact words and phrases, while vector search finds records close in meaning even when worded differently. Many projects combine both — narrowing results with a text filter first, then ranking what's left by vector similarity, gaining precision and flexibility at once.

### What happens if the embedding model used later changes — does the whole database need rebuilding?

Switching the embedding model requires recomputing vectors for every existing record — old and new vectors aren't compatible even if the dimension happens to match, because the numbers encode meaning differently. In practice this means running the dataset through the new model and either overwriting the collection or building it alongside the old one and switching over once it's done.

### Is a dedicated vector database necessary, or can an existing relational database handle it with an extension?

A dedicated vector database earns its place once search load becomes a major part of the system or the data volume grows large: a specialized store uses memory more efficiently and answers that query faster. While a project runs on a relational database and the record count stays moderate, extending it with a vector extension avoids running and maintaining an extra service.

---

Source: https://www.zevshost.net/en/kb/vektornye-bd-sravnenie/
