Skip to content

RVF 0.3.4 does not persist INDEX_SEG; reopened 28k-vector stores take >60s on first query #745

Description

@stuinfla

Summary

The current public packages (@ruvector/rvf@0.3.4, @ruvector/rvf-node@0.2.3, both current latest on 2026-07-30) do not emit a persisted index / INDEX_SEG when an RVF store is created and populated through the documented RvfDatabase.create() + ingestBatch() path.

This makes reopened large stores pay an extreme first-query cost. In RuvNet Brain's real source corpus:

  • 1,466 vectors / 4.4 MB: first query ~5.5s, second query 3-15ms
  • 13,764 vectors / 43 MB: first query exceeded 60s under the measured run
  • 28,152 vectors / 83 MB: first query exceeded 60s under the measured run

The same stores open in 9-105ms. The delay occurs on the first db.query().

Segment proof

db.segments() on the 28,152-vector store reports 330 segments containing only:

  • manifest
  • vec
  • witness
  • journal

There is no index segment. The 1,466-vector store likewise has 23 segments and no index.

A controlled 100-vector reproduction also emits no index:

const db = await RvfDatabase.create(file, {
  dimensions: 4,
  metric: 'cosine',
  m: 16,
  efConstruction: 200,
  overwrite: true,
});
await db.ingestBatch(rows);
console.log(await db.segments());
await db.compact();
console.log(await db.segments());

Before compact: manifest, vec, witness, manifest.
After compact: vec, witness, witness.
Still no index.

Expected

The documented HNSW creation options (m, efConstruction) should produce a durable INDEX_SEG, and openReadonly() should use it so first-query latency is near steady-state query latency rather than scaling into tens of seconds.

If the index is intentionally embedded inside VEC_SEG, please document that layout and investigate why the first query scales this way after reopen. The public README currently identifies 0x02 INDEX_SEG as the HNSW graph segment.

Impact

This blocks an interactive <4s search SLO and caused shared MCP worker timeouts at 30-240 seconds. Raising the timeout is not an acceptable workaround.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions