Here's another approach to the problem [0]:
This package is part of Gazette [1], and uses a gazette journal (known as a "recovery log") to power raw bytestream replication & persistence.
On top of journals, there's a recovery log "hinting" mechanism [2] that is aware of file layouts on disk, and keeps metadata around the portions of the journal which must be read to recover a particular on-disk state (e.x. what are the current live files, and which segments of the log hold them?). You can read and even live-tail a recovery log to "play back" / maintain the on-disk file state of a database that's processing somewhere else.
Then, there's a package providing RocksDB with an Rocks environment that's configured to transparently replicate all database file writes into a recovery log [3]. Because RocksDB is a a continuously compacted LSM-tree and we're tracking live files, it's regularly deleting files which allow for "dropping" chunks of the recovery log journal which must be read or stored in order to recover the full database.
For the SQLite implementation, SQLite journals and WAL's are well-suited to recovery logs & their live file tracking, because they're short-lived ephemeral files. The SQLite page DB is another matter, however, because it's a super-long lived and randomly written file. Naively tracking the page DB means you must re-play the _entire history_ of page mutations which have occurred.
This implementation solves this by using a SQLite VFS which actually uses RocksDB under the hood for the SQLite page DB, and regular files (recorded to the same recovery log) for SQLite journals / WALs. In effect, we're leveraging RocksDB's regular compaction mechanisms to remove old versions of SQLite pages which must be tracked / read & replayed.
[0] https://godoc.org/go.gazette.dev/core/consumer/store-sqlite
[1] https://gazette.readthedocs.io/en/latest/
[2] https://gazette.readthedocs.io/en/latest/consumers-concepts....
[3] https://godoc.org/go.gazette.dev/core/consumer/store-rocksdb