The practical question behind a self-hosted vector database for RAG is which engine fits a given server, and which one the workload rules out. The calculator below answers both, from our benchmark of seven self-hosted vector databases run at matched recall on identical embeddings.
Calculator metrics explained
Five checkboxes at the top of the calculator name five common RAG workloads, and each maps to a measured limit from the benchmark rather than a vendor claim. Checking one filters the engine list against a specific number. Leaving it unchecked means the workload does not apply, and no engine is filtered on it. What each switch asks for, and the measurement behind it:
Selection and sizing
Two decisions precede a running index. The first is selection, because some engines cannot do a given job. The calculator checks each engine against the five requirement switches above and drops the ones that fail. The second is sizing, meaning which of the surviving engines fit the box and with what headroom. For each survivor it reports fits, tight, or does not fit, plus the number of vectors the server would hold. Neither decision turns on retrieval quality, because the seven engines tie within a 0.014 nDCG spread against an exact-kNN oracle.
Footprint at 2.25M vectors
At 2.25M vectors the benchmark measured two footprints, split by where the index lives. For the five in-memory engines it recorded the peak RAM during build and serve, from 17.0 GB (Milvus) to 62.4 GB (Chroma). For the two on-disk engines it recorded the index on disk, 12.0 GB for LanceDB and 18.4 GB for pgvector, which costs far less per gigabyte. Those numbers are the raw measurements, not the calculator’s sizing inputs. The calculator sizes steady-state serving instead.
For the in-memory engines that runs below the build-and-serve peak, and for the on-disk engines it adds the table copy and the chunk text on top of the measured index, so for the same 2.25M corpus its numbers come out lower on RAM and higher on disk than the bars here. The measured-versus-modeled split below reconciles the two. The full per-engine benchmark behind the calculator, across accuracy, speed, filtered and hybrid search, build cost, and live churn, open-source vector database comparison.
The sizing model
The inputs are the corpus size, chunking, and embedding model, and the calculator derives the two numbers that drive sizing. Corpus size and chunking give the vector count. A 2 GB corpus (decimal, 2 billion bytes) at 4 bytes per token is 500M tokens, and 512-token chunks at 15% overlap advance a stride of 512 × 0.85 = 435.2 tokens, so the count is round(500M ÷ 435.2) = 1,148,897 vectors. The embedding model gives the dimension, so the input is a model choice, not a raw number, and bge-m3 sets it to 1024.
Each engine’s footprint is then a per-vector cost multiplied by the vector count, plus a fixed process floor: footprint = base_gb + bytes_per_vector × N. The per-vector cost is where the engines diverge, because a vector database stores more than the raw vector. It also holds the index graph that makes search fast, and, for real RAG, the chunk text it has to return. The table below is the per-vector cost each engine’s storage layout produces at 1024 dimensions in float32.
Two layout facts do most of the separation. Redis keeps a second copy of every vector (a source hash plus an in-index copy) and cannot offload the chunk text, so it is the heaviest in RAM. pgvector stores each vector twice on disk as well, once in the table heap and once inside the HNSW index, and its index rounds up to 8 KB Postgres pages, so a 1024-dimensional float32 vector fills a full page on its own. The four other in-memory engines offload the chunk text to disk, so their RAM cost is the vector plus a small graph. The Store chunk text switch controls that payload, about 2 KB per vector at 512 tokens. Redis holds it in RAM, every other engine keeps it on disk, and turning the switch off removes it everywhere.
The process floor is added once per engine: 2.0 GB for Milvus, 0.5 for Weaviate, 0.3 for Chroma, 0.2 for Qdrant, 0.05 for Redis, and 0 for the two on-disk engines. Putting it together for the default 2 GB corpus (1.15M vectors) on a 16 GB, 200 GB server, Qdrant needs 5.1 GB of RAM, Milvus and Weaviate 6.9 GB, Redis 12.5 GB, while pgvector needs 16.5 GB of disk and LanceDB 8.5 GB.
The verdict compares that footprint to the box on the binding resource, and the 80% line is deliberate headroom. At or below 80% of RAM or disk it reads fits, which leaves about a fifth of the box for the OS page cache, query buffers, and growth. From 80 to 100% is tight, and more does not fit. The figure is steady-state serving, so building or rebuilding the index on the same box needs more RAM for the duration, closer to the measured peak. Running the same formula backwards gives the capacity, (box − base) ÷ bytes_per_vector: the same 16 GB server holds a nominal 1.47M vectors on Redis, 3.7M on Qdrant, and, on its 200 GB disk, 14.0M on pgvector and 27.1M on LanceDB, each within the error band the tool shows next to it rather than a hard line. Turning on quantization divides the vector part (int8 by 4x, product quantization by 16x, binary by 32x) for the engines that support it, and switching the embedding model rescales every number through the dimension.
Measured versus modeled
The calculator separates what the benchmark measured from what it models, since the two carry different confidence. The RAM figures the benchmark recorded are a build-and-serve peak, which runs roughly two to three times higher than steady-state serving, and for Weaviate was inflated by a high Go memory limit. The calculator does not size from that peak. It sizes the five in-memory engines from each vendor’s own documented serving formula, the additive vector-plus-graph costs in the table, and keeps the measured peak as an upper-bound check. So the measurement records what the benchmark observed, while the sizing runs below it on purpose.
The two on-disk engines are the reverse. Their disk index was measured directly and held to within 1 to 2 percent on a held-out corpus, so the calculator sizes them from the measurement. Every capacity carries a visible error band that reflects this split: 25 to 30 percent for the modeled in-memory serving estimates, 15 percent for pgvector, and 1 to 2 percent for LanceDB’s measured disk. Two inputs are labeled as assumptions rather than measurements. The RAM cache for the on-disk engines is set at 25 percent of the index and is editable, because their serving RAM was never measured, and the quantization ratios come from the literature rather than this benchmark, so real recall loss varies with the data.
The capability gate
The selection half of the calculator is a set of binary facts, not a score. The table below is the per-engine side of the switches above. For each engine, it shows the workloads that rule it out and the ones it still does but at a flagged rate. Milvus and Weaviate carry no elimination on any switch, which is why they read as the clean generalists.
Redis is flagged rather than eliminated on durability because it can be made crash-safe with an append-only file. It was benchmarked with persistence off, so the flag notes that the limit is our configuration, not the engine.
Benchmark methodology
The numbers come from a single-server benchmark of the seven engines, each run on its own in a pinned Docker container on a Hetzner CCX53 (32 vCPU, 128 GB RAM, NVMe). Every engine indexed the same bge-m3 vectors (1024-dim, cosine on L2-normalized float32) and was read at a matched Recall@10 of 0.95 reached by sweeping its ef or nprobe, with k=10 and seed 42. The corpora were MedRAG-50k and TechQA-28k for quality and a 2.25M-vector MedRAG tier for scale. The full statistics, confidence intervals, and per-engine versions are in the benchmark article.
Limitations
The in-memory serving figures are vendor formulas calibrated against a build-and-serve peak, not a direct serving measurement, so they carry the 25 to 30 percent band the calculator shows. The serving RAM for pgvector and LanceDB is an unmeasured cache assumption, which is why the calculator sizes those two on disk. The deployment forms also differ by design. LanceDB is an embedded library, pgvector is a PostgreSQL extension, the other five are standalone servers, and Redis ran with persistence off, so each engine’s footprint and rates reflect its own operational shape rather than one identical configuration. The benchmark used one embedding model at 1024 dimensions, so a different model or dimension count shifts every footprint, which is why the model is an input rather than a fixed number. Managed and cloud-hosted engines are a separate comparison.
Conclusion
For a self-hosted vector database in RAG, the pick is a sizing and selection problem rather than an accuracy one, since the seven engines land within 0.014 nDCG of each other. The calculator turns the footprint math and the measured workload limits into one answer for a specific server rather than a leaderboard. On a 16 GB box at 1024 dimensions it holds 1.5M vectors on Redis up to 3.7M on Qdrant in RAM, and 14M to 27M on the on-disk engines, and turning on a churn-heavy workload rules out Chroma and LanceDB while leaving Milvus and Weaviate clear. The measured benchmark behind every one of those numbers is the open-source vector database comparison.
Further reading
- Embedding models benchmark
- Reranker benchmark
- Vector database for RAG
- Open-source embedding models
- Multilingual embedding models
- Multimodal embeddings
- Agentic RAG frameworks
Cite this benchmark
Pick the format that matches where you're publishing. Pasting the link version into your CMS preserves the backlink.
@misc{sari2026,
author = {Sarı, Ekrem},
title = {{Vector Database Sizing and Selection Calculator}},
year = {2026},
month = jul,
howpublished = {\url{https://aimultiple.com/vector-database-for-rag}},
note = {AIMultiple. Retrieved July 20, 2026}
}
Be the first to comment
Your email address will not be published. All fields are required. Comments are left in their original language.