Repository navigation
fix(db): periodically truncate the SQLite WAL on long-running servers - #10781
Merged
diegosouzapw merged 1 commit intoAug 20, 2026
Merged
diegosouzapw merged 1 commit into
diegosouzapw merged 1 commit into
Conversation
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
force-pushed
the
fix/wal-truncate-scheduler
branch
from
August 19, 2026 22:01
d4c6108 to
ab683be
Compare
This was referenced Aug 22, 2026
Closed
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!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
WAL file itself. Only
wal_checkpoint(TRUNCATE)reclaims it, and its single caller iscloseDbInstance()— a long-running server never closes its DB, so the WAL grows until the nextrestart. Observed locally: a 154 MB WAL against a 143 MB database after 24h of uptime.
wal_checkpoint(TRUNCATE)mirroring the existing DB health-check scheduler: sameself-gating (cloud, build phase, automated test process), same
unref()ed interval, same env-varoverride convention. Default 6h;
OMNIROUTE_WAL_TRUNCATE_INTERVAL_MSoverrides it,0disables.Related Issues
Validation
tests/unit/db-wal-truncate-scheduler.test.ts(6/6),npm run test:vitest(368/368),npm run check:env-doc-syncnpm run lintTests Added Or Updated
tests/unit/db-wal-truncate-scheduler.test.ts(new)The scheduler gates itself off under
isAutomatedTestProcess(), like the health-check scheduler itis 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
src/lib/db/core.tsand 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 exercisedwhere
closeDbInstance()uses it.Reviewer Notes
non-fatal; it retries on the next tick.
closeDbInstance()before the shutdown checkpoint, and again on re-open,so no timer leaks between DB instances.
OMNIROUTE_WAL_TRUNCATE_INTERVAL_MSis documented in.env.exampleanddocs/reference/ENVIRONMENT.md; a non-numeric or negative value falls back to the default.