How to estimate pgvector storage and index size
A vector search index is only fast while it stays in memory. Once an HNSW or IVFFlat index spills out of RAM, every query starts reading from disk and latency jumps from milliseconds to hundreds of milliseconds. So the first capacity question for any pgvector project is simple: how big will this index be? The calculator above answers it from four inputs — row count, dimensions, column type and index settings — using the same page layout pgvector uses on disk.
What a vector costs
A vector column stores each dimension as a 4-byte float plus an 8-byte header, so a 1,536-dimension embedding is 6,152 bytes. halfvec uses 2 bytes per dimension, so the same embedding is 3,080 bytes. Vectors larger than about 2 KB are moved out of the main table into TOAST storage, which is why the table estimate is shown as table + TOAST.
Why the index grows in steps, not smoothly
Postgres stores data in 8 KB pages, and pgvector keeps each HNSW element — the vector plus a small header — on the same page as its neighbour list. Elements never split across pages, so what matters is how many elements fit on one page. With the default m = 16:
| Column | Elements per 8 KB page | Index per 1M rows |
|---|---|---|
vector(384) | 4 | ≈ 1.9 GB |
vector(768) | 2 | ≈ 3.8 GB |
vector(1024) | 1 | ≈ 7.6 GB |
vector(1536) | 1 | ≈ 7.6 GB |
halfvec(1024) | 3 | ≈ 2.5 GB |
halfvec(1536) | 2 | ≈ 3.8 GB |
halfvec(3072) | 1 | ≈ 7.6 GB |
The step happens between 946 and 947 dimensions for vector: below it two elements share a page, above it each element gets a page to itself. That is why a 1,024-dimension model costs the same index space as a 1,536-dimension one — and why switching a 1,024-dimension column to halfvec cuts its HNSW index to about a third.
Dimension limits
vectorcolumns can hold up to 16,000 dimensions, but HNSW and IVFFlat can only index up to 2,000.halfveccan be indexed up to 4,000 dimensions — the usual route for 3,072-dimension models.- Above that, reduce dimensions at the model (many providers support it) or index a binary-quantized copy.
Choosing index settings
HNSW: start with pgvector's defaults, m = 16 and ef_construction = 64. Raise m (to 24–32) and ef_construction (to 128–200) for better recall on large or high-dimensional data, at the cost of slower builds and a larger index; ef_construction must be at least 2 × m. At query time, hnsw.ef_search (default 40) trades speed for recall and should be at least your LIMIT.
IVFFlat: build it after loading data. pgvector's guidance is lists = rows / 1000 up to a million rows and √rows beyond, with ivfflat.probes starting at √lists.
Check the real size
Estimates are for planning. Build the index on a representative sample and measure it:
SELECT pg_size_pretty(pg_relation_size('items_embedding_idx')); -- index
SELECT pg_size_pretty(pg_total_relation_size('items')); -- table, TOAST and all indexes
Sizes here use 1024-based units, the same way pg_size_pretty reports them.
Frequently asked questions
How accurate is this pgvector index size estimate?
It models pgvector's real page layout — 8 KB pages, tuple headers, neighbour lists and how many elements fit per page — so it is usually within about 10–15% of the real size. Always confirm on your own data with SELECT pg_size_pretty(pg_relation_size('your_index_name')); after building on a sample.
Why is my HNSW index about 8 KB per row?
pgvector keeps each vector and its neighbour list on the same 8 KB page, and a page cannot be shared once a vector passes roughly half a page. With the default m = 16, any vector column above 946 dimensions fits only one element per page — so 1,024 and 1,536 dimensions cost the same index space. Switching to halfvec halves each vector and usually moves you back to two or more per page.
Should I use vector or halfvec?
halfvec stores each dimension in 2 bytes instead of 4, halving storage and often halving the index. For most embedding models the loss in search quality is very small, but measure recall on your own queries before switching. It is also the only way to index models above 2,000 dimensions, such as OpenAI text-embedding-3-large at 3,072.
What should maintenance_work_mem be for an HNSW index build?
Large enough to hold the graph being built — roughly the vectors plus their neighbour lists, which this calculator estimates. If it is too small, Postgres logs “hnsw graph no longer fits into maintenance_work_mem” and the build continues much more slowly. Set it for the build session only with SET maintenance_work_mem = '…';, and raise max_parallel_maintenance_workers to build in parallel.
HNSW or IVFFlat — which pgvector index should I use?
HNSW gives better speed and recall and can be built on an empty table, at the cost of slower builds and more memory. IVFFlat builds faster and uses less memory, but it must be built after the data is loaded and its recall depends on lists and probes. Most new projects should start with HNSW.
Does this tool send my numbers anywhere?
No. Every calculation runs in your browser. Inputs are kept in the page URL only so you can share or bookmark a sizing.
Built and maintained by Pradeep Bhandari, Senior Engineering Manager & Full-Stack Architect. Last reviewed .