I had a rewrite queued up. Vamana builds a graph by inserting points one at a time, each insertion searching the graph built so far, and at a million vectors that is a long serial climb. Parallel insertion is the obvious fix and it is a real project -- concurrency around a structure that every insert both reads and mutates. Before starting I did the thing I keep having to relearn: measure the current one properly first.

All numbers below are 1M Cohere vectors at 768 dimensions, cosine, on a 32-vCPU machine, one build at a time. Config A -- degree 48, alpha 1.1 -- built in 39.4 minutes. Config B -- degree 32, alpha 1.0 -- built in 59.0. Roughly 49% more time from the config with the SMALLER out-degree, which is backwards from what you would guess. The reason is alpha. It is the slack factor in the pruning rule, and at 1.0 both prune passes run unrelaxed, so the pruner keeps more edges than it needs to. Denser graph, more work per insertion, and a bigger artifact to show for it: 2968 MB against 2934. The footprint turned out to be a reliable fingerprint for which config a build actually ran, which mattered more than I expected later.

So the headline result of a week of build-performance work is a value that was already in the optimizer's search grid the whole time. Nothing to write. Just stop letting alpha 1.0 win on large collections, where the build cost is real and the recall difference is not: config A served at recall 0.9659 with a 11.0 ms p95.

The second lever was scheduling, and it is worth 21 to 31% -- but only against tuning load, not against other builds. One concurrent index build costs a vamana build about 3%. That is the useful shape of it: builds coexist fine, builds and a busy tuner do not, and the fix for that is admission control rather than anything inside vamana.

Parallel insertion stays unbuilt, and I want to be precise about why, because "we measured and decided not to" is a real engineering outcome and it gets written up far less often than shipping does. While vamana builds, a faster-to-build index is already serving the collection -- that is the whole point of building the cheap index first. Nobody waits on the slow one. What is left is 39 minutes of background work on a machine that has nothing else to do, and 39 minutes of idle-machine background work is not worth a concurrency rewrite of the trickiest data structure we run. If a corpus ever gets large enough that those 39 minutes become hours, or if vamana ends up the only viable strategy for a collection, the project comes back. Until then the measurement is the deliverable.