docs-internal/engine/sqlite/constraints-and-design-decisions.md
This page records the constraints that shape the PITR/forking storage design. These are not incidental implementation details.
VTX.The design keeps rough PITR cheap by preserving enough FDB history for branch-at-position recovery without writing a full image for every commit. Exact recovery is opt-in through restore points, which write FDB history pins that workflow compaction must preserve.
Compared with Neon's exact-PITR posture, this trades precision for lower steady-state cost. That fits Rivet Database-style workloads where "fork near this point" is usually enough, and exact restore points can be created explicitly for critical moments.
LTX layers carry page numbers and checksums. That lets the system move bytes between DELTA and SHARD rows without a separate opaque page map. FDB PIDX remains the hot routing index.
The result is an LSM-shaped flow:
Overwriting one SHARD key loses the older materialized image that forks and restore points may still need. Versioned SHARDs keep multiple materializations side by side:
SHARD/{shard_id}/{as_of_txid}
Reads choose the largest as_of_txid <= read_txid. Reclaim deletes old versions only after descendant/restore-point pins and PITR coverage allow it.
This avoids read-your-writes ambiguity after a fork. A child branch can refer to the parent's state at a specific versionstamp while the parent continues compacting and writing newer SHARD versions.
Earlier pointer-based designs needed mutable DBPTR/BUCKET_PTR rows, pointer history, frozen branch state, and cache invalidation when rollback swapped a pointer. The v4 model removes that storage-layer rollback primitive.
Now the external id is the branch id. Forking creates a new immutable branch record with a parent link. Engine-layer rollback is just: fork a new database at the target versionstamp, then update the engine-owned database mapping.
This keeps storage invariants simple:
DatabaseId never points to a different branch later.BucketId never points to a different branch later.Bucket forks must be metadata-only. Eagerly copying every database membership entry would make fork time proportional to bucket size.
BUCKET_CATALOG solves this with parent walks. A bucket fork starts with an empty local catalog and inherits parent catalog entries whose versionstamp is at or before the fork's parent_versionstamp. Tombstones hide inherited entries only along the relevant bucket path.
BranchManifest is a legacy logical struct whose fields are stored under separate subkeys:
CMP/root and manager state.last_access_ts_ms and last_access_bucket.Split keys avoid unrelated read-modify-write conflicts.