Vector at Scale
What you can rely on when a collection stops being small. Each promise below is one claim you can check, with the evidence that backs it.
1. No vector you store can be silently lost
An index build that cannot prove every stored vector reachable fails instead of serving. A lossy index is not a constructible artifact here.
Evidence: every build walks its own graph and re-inserts anything unreachable; the exact residual is carried as a scan tail that search covers, and a tail past 2 % of the corpus fails the build. IVF builds separately verify that every vector lands in exactly one posting list. Verified in every build, every release.
2. A distance you see is the true distance
ANN and quantized indexes only select candidates; every candidate is re-ranked at full f32 precision before it is returned. An index changes which rows you get back, never the distance reported for a row you got.
Evidence: the re-rank is unconditional on the serve path — there is no configuration in which a quantized distance reaches a client.
3. A vector acked is a vector searchable
Fresh writes are searched exactly, with no settle window and no index lag. Vectors that have not yet been sealed into a segment are served by brute force over the growing set, so a write that has been acknowledged is already in the answer.
Check it yourself: insert an embedding and query it back in the same session — it is there. Since tabled v0.1.40.
4. Recall holds as a collection grows, and memory stays bounded
No single graph ever exceeds the size it is good at. A collection’s vectors live in immutable segments of roughly 100 000 vectors, each indexed once; queries fan out across them and merge. Small graphs are better graphs, so recall goes up under segmentation, not down.
Measured, same rows, same serve defaults:
| Corpus | One graph | Segmented |
|---|---|---|
| recall@10, 50 000 × 2048-d | 0.695 | 0.960 |
| recall@10, 200 000 × 64-d | 0.858 | 0.985 |
| build time, 50 000 × 2048-d | 44.5 s | 3.4 s per segment |
| build time, 200 000 × 64-d | 16.1 s | 1.9 s per segment |
Build cost is a function of segment size, never collection size — a 10-million-vector collection builds no differently from its newest slice. And builds are admitted in batches sized against the node’s auto-detected memory budget, sampled at each admission so concurrent builds and the serve path’s own resident indexes share one honest number: an index build cannot OOM the node. Past-budget admission refuses loudly rather than swapping.
That is what lets one bucket hold millions of high-dimensional embeddings with bounded memory and stable recall. Since tabled v0.1.40.
5. Growth and deletion never trigger a rebuild
New data seals new segments; nothing already written is re-indexed. A delete is a mask applied at read and physically dropped when compaction merges segments — it never requires graph surgery and never schedules a rebuild.
Evidence: there is no migration step for a growing collection because none is needed — an existing index reads as one sealed segment and is left untouched. Since tabled v0.1.40.
6. Combinations that would produce wrong answers are refused, with the correct alternative named
The engine will not build an index it knows would rank incorrectly.
CREATE INDEX … USING hnsw_sq_i8 on an inner-product column is refused at DDL
— 8-bit quantization does not preserve the magnitudes inner product ranks by,
and the graph builds fragmented — and the error names hnsw_sq_f16, which is
the same memory tier and clean on that metric.
Evidence: 22 % of vectors measured unreachable at 768 dimensions on that combination, after a full serial rebuild. The refusal costs nothing but a better spelling.
How segmentation works
A collection’s vectors mirror the table’s own write → drain → compact
lifecycle:
- The growing segment is the un-drained set. It carries no index and is searched exactly, which is what makes promise 3 true by construction rather than by timing.
- Sealed segments are immutable slices of roughly 100 000 vectors. Each gets its own index, built once, never rebuilt. The per-segment index structure is the engine’s choice from segment size, dimensions and metric — invisible to you, who declare dimensions and metric and nothing else.
- A query fans out over the growing segment and each sealed segment, merges the per-segment top-k, and re-ranks the merged candidates exactly.
- Compaction merges small or heavily-tombstoned segments the same way it merges table files.
The correctness net travels per segment: the reachability proof of promise 1 is asserted on every segment build and end-to-end through the merge, so a vector returns itself across any segment layout.
What is not here yet
Stated so you can plan around it rather than discover it:
- Filtered KNN pushed into the index — a metadata predicate evaluated inside the ANN search. Filtered KNN works today by over-fetching candidates and re-checking the predicate exactly (never silently under-filled); pushing the predicate down is designed and not yet shipped.
- PQ and DiskANN tiers — a later rung on the same ladder, with the same gates.
See also
- ANN Indexes — declaring an index and choosing its kind
- Core Concepts — the
vector<n>type model - Reservation & Hot Cache — the memory budget segments are served under