skills/litestream/references/SQLITE_INTERNALS.md
Condensed reference for agents working with SQLite internals in Litestream.
database.db Main database file (pages)
database.db-wal Write-ahead log
database.db-shm Shared memory file (coordination)
WAL is SQLite's method for atomic commits:
+------------------+
| WAL Header | 32 bytes
+------------------+
| Frame 1 Header | 24 bytes
| Frame 1 Data | PageSize bytes
+------------------+
| Frame 2 Header | 24 bytes
| Frame 2 Data | PageSize bytes
+------------------+
| ... |
Magic (4B) | FileFormat (4B) | PageSize (4B) | Checkpoint (4B) |
Salt1 (4B) | Salt2 (4B) | Checksum1 (4B) | Checksum2 (4B)
Magic: 0x377f0682 or 0x377f0683
PageNumber (4B) | DbSize (4B) | Salt1 (4B) | Salt2 (4B) |
Checksum1 (4B) | Checksum2 (4B)
SQLite reserves a page at exactly 0x40000000 bytes (1 GB) for locking. This is the single most important SQLite detail for Litestream development.
const PENDING_BYTE = 0x40000000
func LockPgno(pageSize int) uint32 {
return uint32(PENDING_BYTE/pageSize) + 1
}
| Page Size | Lock Page Number |
|---|---|
| 4 KB | 262145 |
| 8 KB | 131073 |
| 16 KB | 65537 |
| 32 KB | 32769 |
| 64 KB | 16385 |
Rules:
Implementation in Litestream:
for pgno := uint32(1); pgno <= maxPgno; pgno++ {
if pgno == ltx.LockPgno(db.pageSize) {
continue
}
processPage(pgno)
}
SQLite divides databases into fixed-size pages (typically 4096 bytes):
UNLOCKED → SHARED → RESERVED → PENDING → EXCLUSIVE
Litestream maintains a read transaction for consistency:
func (db *DB) initReadTx() error {
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{ReadOnly: true})
if err != nil {
return err
}
var dummy string
err = tx.QueryRow("SELECT ''").Scan(&dummy)
if err != nil {
tx.Rollback()
return err
}
db.rtx = tx
return nil
}
Purpose:
| Mode | Behavior |
|---|---|
| PASSIVE | Non-blocking; fails if readers present |
| FULL | Waits for readers; blocks new readers |
| RESTART | Like FULL + resets WAL start (removed in #724) |
| TRUNCATE | Like RESTART + truncates WAL to zero |
WAL pages > TruncatePageN → TRUNCATE (emergency)
WAL pages > MinCheckpointPageN → PASSIVE
CheckpointInterval elapsed → PASSIVE
Note: RESTART mode permanently removed due to issue #724 (write-blocking).
PRAGMA journal_mode = WAL; -- Required for Litestream
PRAGMA page_size; -- Get page size
PRAGMA page_count; -- Total pages in database
PRAGMA freelist_count; -- Free pages
PRAGMA wal_checkpoint(PASSIVE); -- Non-blocking checkpoint
PRAGMA wal_autocheckpoint = 10000; -- High threshold (prevent interference)
PRAGMA busy_timeout = 5000; -- Wait 5s for locks
PRAGMA synchronous = NORMAL; -- Safe with WAL
PRAGMA cache_size = -64000; -- 64 MB cache
PRAGMA integrity_check; -- Verify database integrity
Litestream converts WAL frames to LTX:
pgno == LockPgno(pageSize))