lance-format / lance-format/lance
Tracking: Distributed Indexes Search
@Xuanwo is already working on this.
Since Mar 27, 2026.
- Dominant language
- Rust
- Stars
- 7.1k
- Forks
- 852
- Avg merge
- 3d 18h
- Merged PRs (30d)
- 272
Description
Lance is making distributed indexing a first-class capability by unifying all index
families on a global segment model: a logical index is a set of physical segments, and
build, commit, query, append, optimize, and GC all operate on segment sets.
Distributed indexing should not be a special path; it should be the natural
consequence of a segment-native index system.
Target interface — the contract we are building toward
Every index family must converge on the same segment-native interface. Contributions that bypass it — by adding a per-type distributed path, or by repurposing an identifier or directory as coordination state — are built on the wrong model even when they pass tests. Please align new work with the contract below.
Data model. A logical index is a set of physical segments. Each segment has its own physical UUID, lives at _indices/<segment_uuid>/, is self-contained and immutable once built, and covers a disjoint set of fragments (segments in one logical index never overlap). build, commit, query, append, optimize, and GC all operate on segment sets, so distributed indexing is just "build N segments on N workers, then commit them as one logical index" — not a special code path.
Canonical build workflow (identical for every index type):
create_index_uncommitted(column, index_type, fragment_ids=...)— each worker builds one uncommitted segment from its assigned fragment subset; returns segment metadata, does not touch the manifest.merge_existing_index_segments(segments)— build the staged segments into the final physical segment set.commit_existing_index_segments(index_name, column, segments)— publish the segment set as one logical index in a single transaction.
The four per-family capabilities tracked below map onto this workflow: distributed build (step 1) · distributed merge (inside step 2 / the primitive) · commit (step 3) · distributed multi-segment query.
Anti-patterns — do not build on these:
- ❌ Treating
index_uuidas a shared merge directory or job id (the legacy Bitmapmerge_index_metadata(index_uuid, "BITMAP")+shard_idmodel). A physical segment is identified by its own UUID, not by a coordination handle. - ❌ Adding a bespoke distributed or merge path for a single index type instead of implementing the hooks behind the canonical API above.
- ❌ Merging by stitching metadata or sharing a directory across workers, instead of rewriting into a new self-contained segment.
Adding a new index family means implementing these hooks — not inventing a parallel path.
Cross-cutting foundation (index-type agnostic)
The segment model, transaction semantics, commit/validation, and the multi-segment
query plumbing are shared across all families.
- Clarify logical indices vs physical segments — #6270
- Index segment commit API — #6209; preserve create-index transaction semantics — #6204
- Align distributed index build around segments — #6313
- Preserve index details in index metadata — #6279
- Enforce
fragment_bitmapdisjoint coverage at commit time - Make append and optimize segment-set-native — lance-format/lance#6398
- Index reader for segmented index — lance-format/lance#6399
- Crash / partial-failure recovery for in-flight distributed builds
- Ownership + cleanup sweep for stale uncommitted index artifacts (GC)
Vector (IVF_FLAT / IVF_SQ / IVF_PQ / IVF_RQ / IVF_HNSW_*)
IVF family (FLAT/SQ/PQ/RQ) has all four capabilities. HNSW variants build/commit/query
but merge discards the graph (degrades to brute-force IVF), so HNSW relies on the
non-shared-centroid build+commit+query path instead of merge.
- Distributed vector segment build — #6220
- Remove staging from distributed vector indexing — #6269
- Non-shared centroid (per-segment) builds — #6296
- Distributed IVF_RQ segment builds — #6359
- Vector query pruning by index segments — #6376
FTS / Inverted
Segmented build + merge + commit + multi-segment search with a shared global BM25 scorer
all landed (lance-format/lance#6305). Remaining work is the efficiency layer for multi-segment search.
- Segmented inverted build + multi-segment search with shared global BM25 — lance-format/lance#6305
- Recompute WAND block-max upper bounds under global IDF
- Compact / optimize FTS as a segment-set rebuild from source data
Scalar (BTree / Bitmap / LabelList / NGram / ZoneMap / BloomFilter / RTree)
Commit and multi-segment query are index-type-agnostic and already work for all scalar
families. The gap is distributed build (only BTree/Bitmap today) and merge (none yet — merge_existing_index_segments accepts only vector/inverted).
- Scalar single-source segment metadata — #6279
- BTree: segmented planning + merge — lance-format/lance#6979 (PR #6889)
- Bitmap: align with segmented index lifecycle — lance-format/lance#6862 (PR lance-format/lance#6869)
- LabelList / NGram / ZoneMap / BloomFilter / RTree: decide whether each needs
distributed build + merge (today they reject fragment-scoped training)
References
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.