A graph you can walk towards the answer
Every vector becomes a node connected to some of its near neighbours. A search starts anywhere and repeatedly steps to whichever neighbour is closer to the query.
That walk converges quickly and gets stuck in local minima, because a node's neighbours may all be further away while a much better region sits elsewhere.
The fix is hierarchy. Upper layers hold a sparse sample of the nodes with long-range links, and each layer below is denser and more local.
A node's top layer is drawn from an exponential distribution, so most nodes exist only at the bottom and a few reach the top.
The search
- Enter at the single node in the top layer.
- Walk greedily in that layer until no neighbour is closer.
- Drop to the layer below, starting from where you stopped.
- Repeat, so each layer refines the previous one's answer.
- In the bottom layer, keep a candidate list of size rather than a single best node.
The upper layers cover distance in few steps and the lower layers cover detail, which gives a logarithmic expected number of hops.
The bottom-layer beam is the one knob that matters at query time. Larger means more nodes visited, higher recall and proportionally more latency.
The build parameters
Each node keeps up to neighbours per layer, typically 16 to 64. It is fixed at build time and it sets both the memory and the connectivity.
A million 768-dimensional float vectors with is about 3 GB of vectors and 250 MB of graph, and all of it has to be in RAM.
During insertion the same beam search finds each new node's neighbours. A larger value builds a better graph slowly and does not affect query speed at all.
Why the neighbour selection is not simply the nearest
Linking each node to its closest neighbours produces clusters that are densely connected inside and barely connected to each other.
The heuristic instead keeps a neighbour only if it is closer to the node than to any already-selected neighbour, which deliberately preserves some long links.
Those links are what let the walk cross between clusters, and without them recall collapses on clustered data even though the graph looks well built.
What it costs to operate
Deletes are soft.
Removing a node would break the paths that run through it, so deletions are marked rather than applied, and the graph is periodically rebuilt.
Building is expensive, roughly distance computations with a large constant, and it cannot be meaningfully parallelised across machines.
That is the summary of HNSW: the fastest recall per millisecond available, in exchange for holding everything in memory and rebuilding when the corpus changes shape.