Embedding Storage Calculator

What a vector database costs to hold. The driver is vector count multiplied by dimensions, and vector count is where the surprises live: a small corpus chunked finely at 3,072 dimensions lands where a large one summarised at 384 does, and a late-interaction model storing one vector per image patch lands two orders of magnitude above both.

Corpus

Estimated at 1.33 tokens per word. Length spread across documents does not change the answer, except where documents are shorter than one chunk.

Overlap raises the vector count and duplicates stored text, so the payload exceeds the size of the original corpus.

Index

 

Models trained with Matryoshka representation can be truncated to a shorter prefix with limited accuracy loss.

Total on disk

--

 

Vectors Index Payload Metadata

ComponentSize
Vector data--
Index structure--
Payload--
Metadata and ids--
Total--

Resident memory for low latency

--

 

The graph is traversed on every query, so it stays in memory whatever the vectors do. Quantising to int8 shrinks the vectors and leaves the graph untouched, which is why the saving is smaller than the ratio suggests at low dimensions.

    Same corpus, different dimensions

    Total on disk for the current vector count, holding everything else fixed. Truncating a Matryoshka model from 1,536 to 384 dimensions moves you three rows up this table.

    Dimensions float32 float16 int8 binary
    384 -- -- -- --
    768 -- -- -- --
    1024 -- -- -- --
    1536 -- -- -- --
    3072 -- -- -- --
    4096 -- -- -- --

    Same corpus, different chunking

    Vector count and total at the current dimensions and precision. Halving the chunk size roughly doubles everything.

    Chunk size Vectors Vector data Total on disk
    128 tokens -- -- --
    256 tokens -- -- --
    512 tokens -- -- --
    1024 tokens -- -- --
    2048 tokens -- -- --

    Method

    Everything reduces to vector count multiplied by dimensions. For text, vectors per item is the number of chunks a document produces; for images it is one, unless the model keeps a vector per patch or per token:

    chunks_per_doc = max(1, ceil((doc_tokens - overlap) / (chunk_size - overlap)))
    vector_count = items × vectors_per_item
    vector_bytes = vector_count × dimensions × precision_bytes

    The max(1, ...) matters more than it looks. A corpus of 200,000 support tickets at 40 tokens each still produces 200,000 vectors, not the 17,000 a divide-the-total estimate returns.

    HNSW adds a navigable graph. Layer zero holds twice M bidirectional links per node and the upper layers add roughly 15% more, stored as 32-bit ids. IVF stores centroids plus a list assignment per vector, with the list count sized at the square root of the vector count. Flat indexes add nothing beyond the vectors:

    hnsw_bytes = vector_count × 2M × 4 × 1.15

    Metadata is charged per stored row. Single-vector models write one row per vector; late-interaction models normally hold their patch vectors as an array on one row per item, so metadata is charged per item there instead.

    Text payload is estimated at four bytes per token, which holds for English in UTF-8. Because overlapping chunks duplicate their shared tokens, stored text exceeds the corpus by roughly the ratio of chunk size to stride.

    Background: why vector databases are difficult, data methods for RAG, event-driven embeddings in PostgreSQL, and model choice and VLM inference cost. Related: the inference VRAM calculator. (If you are sizing this against a real corpus, get in touch.)