Skip to content

[Feature] Make FTS index rebuild incremental (full 90-min re-index on every sync) #28

Description

@Vankir

Feature Description

Make the FTS (full-text search) index rebuild incremental. Currently every compile / watch --once --repo / graph refresh run does a full DROP + recreate + re-index of the SQLite FTS tables, regardless of how many files actually changed — even a single new note triggers a complete rebuild of the entire index.

Motivation

On large vaults (e.g. 2500+ sources, ~8600 wiki pages) the full FTS rebuild dominates the compile pipeline:

  • ~70–80% of compile/watch runtime is spent in rebuildSearchIndex (verified in engine chunk-2PN46RDI.js, line ~19517): it DROP + re-creates pages/page_search, re-reads every wiki page file + manifest, parses frontmatter, then runs a full FTS5 re-index (INSERT INTO page_search SELECT ...).
  • A clean run with zero changes takes the same 85–93 minutes as a run that changed 100 files. There is no incremental path at all.
  • This makes the tool impractical for daily-driver workflows: adding one note to the vault costs ~1.5 hours of CPU on the next sync, and on constrained hardware (1 vCPU VPS) it risks sustained-load throttling.

The LLM analysis phase (ingest) is already incremental — only new/changed files get analyzed. The search index is the outlier.

Proposed Solution

A few possible directions (any would help):

  1. True incremental FTS: track per-source content hashes (already computed for ingest dirty-checking) and only re-insert/delete the rows for pages whose source content or generated wiki page changed, instead of dropping all tables.
  2. Skip FTS rebuild when nothing changed: reuse the existing dirty/hash logic — if no sources, no wiki pages, and no graph pages changed since the last index build, leave fts-000.sqlite untouched (fast path: seconds instead of 90 min).
  3. Separate the FTS rebuild from the graph/wiki generation so it can be scheduled independently (e.g. nightly) rather than running on every graph refresh --file.

Option 2 alone would remove the largest cost for the common "no changes / few changes" case without a full engine rewrite.

Alternatives Considered

  • Telling users to run syncs less often (every 2–3 days) — works around the problem but keeps the 90-min worst case on every actual change.
  • Disabling the FTS rebuild entirely — not acceptable, since the search index is what makes query fast (~5s vs ~45s for raw grep over the vault).
  • Switching to an external incremental indexer — heavy integration cost; native fix is preferable.

Environment

  • Version: 3.20.0 (npm / GitHub Releases latest)
  • Vault: ~2500 sources, ~8600 wiki pages, FTS index ~1.27 GB
  • Hardware: 1 vCPU / 3.8 GB RAM (constrained — makes full rebuilds especially painful)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions