What is steady-state memory?
Steady-state memory is the amount of RAM an HNSW process occupies once construction temporaries have been released and the index is in normal service — the durable footprint of vectors, graph edges, and metadata that must stay resident for fast queries.
How does steady-state memory differ from peak build memory?
Peak build memory is a high-water mark during insertion, when efConstruction candidate lists, per-thread scratch, and a growing graph coexist. Steady-state memory is what remains after that crest: the finished (or stably loaded) vector store, neighbor-ID arrays, per-node records, and whatever long-lived caches the implementation keeps. The gap between the two can be large; a machine that survives the build still needs enough headroom above steady state for query scratch and the OS. Capacity planning therefore uses two numbers: peak to finish ingest safely, and steady state to run the service day after day. Quoting only one of them mis-sizes either the build job or the serving fleet.
The steady-state figure is essentially what bytes-per-vector accounting is trying to predict for the live index.
What makes up steady-state memory in a typical HNSW service?
Dominant terms are vector payloads (N × d × element size, plus row padding) and graph edges (average degree × ID width × bidirectional storage). Fixed per-node metadata, locked or atomic headers, and any always-on vector cache sit beside them. Query concurrency adds a smaller but real layer: each in-flight search needs heaps and a visited structure proportional to efSearch and N’s ID space representation. Under read-mostly load those scratch regions are rented and returned continuously, so RSS may sit a bit above the pure index estimate without matching peak build. In-memory systems such as Weaviate treat this resident graph-plus-vectors set as the central memory budget for HNSW collections, which is why reducing dimensions, quantizing, or lowering M changes steady state more reliably than micro-optimizing a distance kernel.
Steady state is also not perfectly flat: deletes, inserts, and caches make it a band rather than a single point.
Why does live steady-state memory drift after the initial build?
Online insertions grow vectors and edges; tombstones and fragmentation can prevent RSS from shrinking as fast as logical deletions. A software vector cache may expand toward a configured maximum, then drop and refill. Memory-mapped object stores can pull extra pages into the process’s view under query load even when the HNSW graph itself is already accounted for. Allocator freelists may retain arenas after a bulk delete until compacted. Measuring steady state therefore means sampling after the system has been answering traffic for a while — not only immediately after build — and noting upsert rate and cache settings. A “quiet” RSS right after load can understate the plateau you will see in production.
Operators use steady-state memory to decide shard size, replica count, and when quantization becomes mandatory.
How should you use steady-state memory when sizing and tuning HNSW?
Estimate with bytes-per-vector × N, validate against RSS under representative QPS, and leave margin for query scratch, page cache if applicable, and growth until the next scale-out. If steady state does not fit in RAM, options are quantize vectors, reduce M (trading recall or needing higher efSearch), shard across machines, or move to a disk-tiered design — not merely adding build-time flags. If steady state fits but peak build does not, keep serving size as-is and constrain build concurrency or efConstruction instead. Track steady-state bytes-per-vector over time so layout regressions and delete accumulation show up before OOM. Steady-state memory is the long-term tax of keeping HNSW fast; pay it deliberately.
Steady-state memory is the durable RAM footprint of a live HNSW index after build spikes settle — the number that governs serving capacity. From here, peak build memory covers the ingest crest, bytes-per-vector accounting breaks down the estimate, graph and vector storage overhead pages deepen each bucket, and the chapter on laying out HNSW in memory shows how layout choices move the plateau you run in production.