Skip to content

Move thread-list SQLite reads off the serving loop - #4

Merged
Guitaraholic merged 1 commit into
mainfrom
fix/sqlite-read-worker
Sep 2, 2026
Merged

Move thread-list SQLite reads off the serving loop#4
Guitaraholic merged 1 commit into
mainfrom
fix/sqlite-read-worker

Conversation

@Guitaraholic

@Guitaraholic Guitaraholic commented Sep 2, 2026

Copy link
Copy Markdown

Human comments

What was wrong

better-sqlite3 is synchronous. Thread-list and sidebar reads ran on the Node serving loop. One cold query on a 1.7GB bb.db froze every client for 11s, including WebSocket token streams. Related: get-bb/bb#1131.

What changed

  • File-backed servers start one readonly WAL worker (packages/db + apps/server/src/sqlite-read-worker.ts).
  • Thread list and sidebar project+thread reads go through listThreadsWithPendingInteractionStateOffThread (and the project-scoped variant).
  • :memory: tests and a worker that fails to start keep the existing sync path.
  • Bundled servers also emit dist/sqlite-read-worker.js.

Search and timeline reads stay on the serving connection. No protocol change.

Why this way

T3’s second rule: never block the Node serving loop on a synchronous SQLite read. A readonly WAL worker is the smallest move that keeps better-sqlite3 and WAL, and only relocates the queries that already froze the loop (thread list, sidebar).

We did not migrate to async sqlite, did not rewrite the schema, and did not move search or timeline yet. Those are more surface area for the same idea. Writes stay on the serving connection; the worker is read-only so it cannot fight the writer.

Benefit to bb

Local and desktop servers with a large db. Token streams, reconnect, and opening another thread keep running while a sidebar query is in flight. A hosted server that uses this worker gives the same to web clients.

Harvest

Independent. Already opened: get-bb/bb#2936.

Decision record: docs/perf-control-plane.md (PR #9).

How you verified

  • Added packages/db/test/sqlite-read-queue.test.ts: in-memory stays on the calling connection; a file-backed worker returns the same thread list as the serving connection.

Related: get-bb#1131, get-bb#2936

AGENT GENERATED

Synchronous better-sqlite3 on a large db froze every client. File-backed
servers now run one readonly WAL worker for thread list and sidebar
project+thread reads. In-memory tests and a worker that fails to start
keep the existing sync path.

Fixes get-bb#1131
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant