🧠 Vector Index Memory
A vector index is two data structures: the vectors, and the graph that searches them. One million 1,536-dimension embeddings at float32 is 5.72 GiB. The HNSW links that find them add another 0.12 GiB. Quantize to binary and the vectors fall 32× while the links do not move at all, which is why the graph goes from 2% of your RAM to 41% of it.
📐 Index Configuration
Enter the collection shape and the precision you store it at. The engine computes vector bytes, HNSW link bytes and total resident memory. Graph links follow the HNSW paper: layer zero holds 2M links per vector, upper layers add M/(M-1) more, each link is a 4-byte node id.
Two Data Structures, One Memory Bill
Almost every vector database sizing exercise starts with the same multiplication: vectors × dimensions × bytes per dimension. That product is correct, and it is also incomplete, because a graph-based index stores a second structure alongside the vectors. In HNSW every vector becomes a node, and every node carries a list of neighbour ids at each layer it appears in. Those ids are not free, they do not compress with the vectors, and at high vector counts they are large enough to change which node size you buy.
links/vec = 2M + M/(M-1) layer 0 is 2M, upper layers add M/(M-1)
graph = N × links/vec × 4 each link is a 4-byte node id
total = vectors + graph + payload
The 2M term comes from the HNSW paper: layer zero keeps twice the base connectivity, and each element is promoted to higher layers with probability 1/M, so the upper layers contribute a geometric series that sums to M/(M-1). At M=16 that is 32 + 1.07 links, or 33.07 links per vector, or 132 bytes. It is a small number next to a 6,144-byte float32 vector, and that is exactly why it gets ignored.
The Numbers for One Million Documents
Hold the collection fixed at one million vectors of 1,536 dimensions and vary only the precision. The vector column falls by 32× from top to bottom. The graph column does not move, because M is a property of the index and not of the vector.
| Precision | Bytes/vector | Vectors | Graph (M=16) | Total | Graph share |
|---|---|---|---|---|---|
| float32 | 6,144 | 5.72 GiB | 0.12 GiB | 5.85 GiB | 2.1% |
| float16 | 3,072 | 2.86 GiB | 0.12 GiB | 2.98 GiB | 4.1% |
| int8 | 1,536 | 1.43 GiB | 0.12 GiB | 1.55 GiB | 7.9% |
| binary | 192 | 0.18 GiB | 0.12 GiB | 0.30 GiB | 40.8% |
Read the last column rather than the totals. Going from float32 to binary cuts the index by 19×, which is the headline everyone quotes. The composition of what remains is the part nobody quotes: two fifths of the resident memory is now neighbour ids, not vectors. You have finished optimizing the thing you were optimizing and arrived at a different bottleneck.
Why Quantization Moves the Bottleneck to M
Once the vectors are 192 bytes, the only remaining lever is the link structure, and the link structure scales with M rather than with dimensions. Doubling M from 16 to 32 takes links per vector from 33.07 to 65.03, which takes the graph from 132 bytes to 260 bytes. On the binary collection that pushes graph share from 41% to 57.5%. On the float32 collection the same change is invisible.
The practical consequence is a sequencing rule. Decide the precision first, because it dominates while vectors dominate. Then, if you quantized aggressively, re-examine M, because you have just made the graph the largest single component. Tuning M on an unquantized collection and then quantizing without revisiting M is how a carefully right-sized index ends up either oversized or short on recall for reasons that no longer correspond to the numbers you tuned against.
The Rerank Store You Still Have to Pay For
Binary and int8 quantization usually come with a rescoring step: the quantized vectors produce a candidate list cheaply, and the full-precision vectors rescore that list to recover accuracy. That is an excellent design, and it means the quantized collection is often not the only copy of your embeddings. If the originals are kept in memory, or in a second collection, the memory you saved is memory you moved rather than memory you removed.
Before sizing a node against a quantized number, ask one question of your engine: are the quantized vectors the only copy? If the answer is no, model the full-precision collection as well and add the two. The savings are still real when the originals live on disk or in object storage, but they are a latency and IO trade rather than a pure win, and the node size should reflect which of those you actually bought.
What This Calculator Does Not Count
Everything above is index residency: vectors, links, and any payload bytes you enter. Four things are deliberately outside the model, and each of them can be larger than the rounding error you are worried about.
Allocator overhead. Memory allocators serve requests in size classes, so a 6,144-byte vector may occupy a slightly larger slot. The effect is usually 10% to 20% of total allocation and depends on the allocator and on how many small objects exist alongside the vectors.
Replicas. A three-replica deployment multiplies the whole model by three before any other factor. This is the single largest omission in most sizing spreadsheets because it is a topology decision rather than a data property.
Deleted and tombstoned vectors. Deleting a point does not always return its slot immediately. Some engines mark the slot and reclaim it during a later compaction pass, so a collection that has churned can be meaningfully larger than its live count implies.
Id maps and metadata indexes. Engines maintain a mapping from internal node ids to external identifiers, and any filterable metadata field has its own index. Both grow with vector count, and neither appears in the three-line formula above.
If you are sizing a node for a production collection, take the number this page gives you and add the replica multiplier first, then a 10% to 20% allocator allowance, then whatever your metadata footprint actually measures. Treat the output as a floor for the data structure and not a quote for the deployment.
Where This Fits
This is the storage half of the RAG capacity question. The compute half is tokenization and embedding throughput, which is a different model with a different unit: tokens rather than bytes. If you are sizing a retrieval system end to end, pair this number with a token-to-storage estimate for the source corpus and an inference cost model for the embedding and generation calls, because the three scale with different inputs and are rarely proportionally sized.
The dimensions themselves are worth checking before you trust any of this. A 3,072-dimension model doubles the vector column against a 1,536-dimension model for the same collection, and a 1,024-dimension model cuts it by a third. Dimension count is a property of the model you chose, not a constant, and it is the cheapest variable in the entire calculation to change.