Sync / foldkit-durable

Retention

Two kinds of row grow for the life of the database and are never collected: one identity row per distinct opId, kept after compaction so an old retry is recognized, and one record per effect key. Growth follows the number of distinct operations and effects, not only retained payload size.

Compaction empties payloads but SQLite keeps their pages. vacuum() rebuilds the file and checkpoints its write-ahead log; it holds the database while it runs, so schedule it as maintenance. A reader on another connection can block the log truncation, in which case vacuum fails with JournalError and a later run finishes the job.

If you rotate or recreate the database, an operation whose identity row is gone is indistinguishable from new work. Reject work older than the retained window instead of applying it as new: keep a per-document watermark, or refuse an operation whose base cursor predates the floor.