Skip to content

fix(db): periodically truncate the SQLite WAL on long-running servers - #10781

Merged
diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.50from
maxmad64bis:fix/wal-truncate-scheduler
Aug 20, 2026
Merged

diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.50from
maxmad64bis:fix/wal-truncate-scheduler

Conversation

@maxmad64bis

Copy link
Copy Markdown
Contributor

⚠️ base-red inherited: #9985

Summary

  • SQLite's auto-checkpoint moves WAL pages back into the main database file but never shrinks the
    WAL file itself. Only wal_checkpoint(TRUNCATE) reclaims it, and its single caller is
    closeDbInstance() — a long-running server never closes its DB, so the WAL grows until the next
    restart. Observed locally: a 154 MB WAL against a 143 MB database after 24h of uptime.
  • Adds a periodic wal_checkpoint(TRUNCATE) mirroring the existing DB health-check scheduler: same
    self-gating (cloud, build phase, automated test process), same unref()ed interval, same env-var
    override convention. Default 6h; OMNIROUTE_WAL_TRUNCATE_INTERVAL_MS overrides it, 0 disables.

Related Issues

  • None filed upstream.

Validation

  • Change type: DB
  • Focused tests and category gates from the golden path:
    tests/unit/db-wal-truncate-scheduler.test.ts (6/6), npm run test:vitest (368/368),
    npm run check:env-doc-sync
  • npm run lint
  • Reconciled with the current active release base; focused checks rerun afterward
  • Production-code changes include a new or updated automated test in this PR
  • SonarQube is temporarily opt-in while the private project has no quota; it is not a PR gate.

Tests Added Or Updated

  • tests/unit/db-wal-truncate-scheduler.test.ts (new)

The scheduler gates itself off under isAutomatedTestProcess(), like the health-check scheduler it
is modeled on, so the test reads the wiring rather than running it — same approach and helper as
tests/unit/lib/jobRegistry/boot-wiring.test.ts.

Coverage Notes

  • The new code lives in src/lib/db/core.ts and cannot execute under the test runner by design:
    the same gate that keeps the existing health-check scheduler from starting in tests applies to
    it. The test therefore pins the wiring, the env-var contract and the shutdown/re-open cleanup at
    source level. The behavior itself is one checkpointDb(db, "TRUNCATE") call, already exercised
    where closeDbInstance() uses it.

Reviewer Notes

  • TRUNCATE waits for readers and can no-op under concurrent write load. That is expected and
    non-fatal; it retries on the next tick.
  • The timer is cleared in closeDbInstance() before the shutdown checkpoint, and again on re-open,
    so no timer leaks between DB instances.
  • OMNIROUTE_WAL_TRUNCATE_INTERVAL_MS is documented in .env.example and
    docs/reference/ENVIRONMENT.md; a non-numeric or negative value falls back to the default.

SQLite's own auto-checkpoint (default: every 1000 WAL pages) moves
pages back into the main database file, but only
wal_checkpoint(TRUNCATE) shrinks the WAL file itself back down - a WAL
never shrinks on its own. closeDbInstance() already truncates on
shutdown, but a long-running server never closes its database, so the
WAL keeps growing indefinitely between restarts.

Measured locally on a permanent instance: the WAL file grew from 4.2 MB
back up to 153.9 MB - larger than the 150.9 MB database it protects -
in under 24 hours after a manual truncate, with freelist_count at 0 (so
this is not a VACUUM/bloat problem, the database is full of real data).

Add a periodic scheduler mirroring the existing DB health-check
scheduler (same self-gating against cloud/build/test contexts, same
unref'd interval, same env-var override convention). TRUNCATE waits for
readers and can no-op under concurrent write load; that is expected and
non-fatal, it retries on the next tick.
@maxmad64bis
maxmad64bis force-pushed the fix/wal-truncate-scheduler branch from d4c6108 to ab683be Compare August 19, 2026 22:01
@diegosouzapw
diegosouzapw merged commit d82e3cf into diegosouzapw:release/v3.8.50 Aug 20, 2026
5 checks passed
@maxmad64bis
maxmad64bis deleted the fix/wal-truncate-scheduler branch September 24, 2026 21:16
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…diegosouzapw#10781)

Merged via merge-train (release/v3.8.50, batch1 2026-08-20) — static gates (typecheck/file-size/complexity/cognitive/changelog) green on the combined tree; test:unit reds observed in the boarded run were verified pre-existing on the pure release tip (unrelated flake), not caused by this PR. Thanks for the contribution!
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.

2 participants