Time-travel is a first-class feature, not an add-on: because the engine is built around a publish-then-serve lifecycle and keeps every published snapshot by default, the database is a versioned point-in-time history. Any past state can be queried as if it were current.
That buys real capabilities on a batch-write / read-heavy workload:
The dl CLI exposes the timeline directly — record a point-in-time with publish, list the history with versions, and run queries as-of a past snapshot with --version N:
$ ./dl -d /tmp/db publish Snapshot published. $ ./dl -d /tmp/db versions 1 2 3 # Query as-of a past snapshot — full-text and semantic search both support --version. $ ./dl -d /tmp/db search 'gpu rental' --top 10 --version 2 $ ./dl -d /tmp/db vsearch 'GPU rental' --k 10 --version 2
The version-aware C API is dl_query_version, dl_search_version, and dl_vector_search_version (see the C API).
Each successful publish produces a monotonically increasing version number starting at 1. Enumerate the available versions ascending with dl_snapshot_versions, using the two-call idiom:
long total = dl_snapshot_versions(db, NULL, 0); /* size */ uint32_t *vers = malloc((size_t)total * sizeof(*vers)); dl_snapshot_versions(db, vers, (size_t)total); /* fill */ free(vers);
It returns the total number of versions even when the output buffer is smaller (filling at most cap entries), returns 0 when no snapshot has been published, and -1 on a NULL db.
Query a relation as of a specific published version with dl_query_version, or bind leading columns with dl_query_bound_version:
long n = dl_query_version(db, version, "edge", cb, user); long m = dl_query_bound_version(db, version, "edge", leading, k, cb, user);
Semantics and guarantees:
db->snap_version is never mutated, so live/current routing is untouched.dl_query stays on the current version until the next publish.By default every version is kept forever. To bound disk usage, opt in to prune-to-N with dl_set_snapshot_retain: after each successful publish, the oldest versions beyond the most-recent n are pruned. n == 0 (the default) restores keep-all.
dl_set_snapshot_retain(db, 5); /* keep the 5 most-recent versions */ dl_set_snapshot_retain(db, 0); /* back to keep-all */
A pruned version is gone — querying it returns -1 (loud), matching the nonexistent-version contract.
This fits the engine’s single-writer / multiple-reader model. Readers hold mmap views and keep reading valid data even after a retention prune unlinks the underlying snapshot directory. A reader holding an mmap of snapshots/<V>/<rel>.dafsa keeps reading valid data after the pruner removes the directory — the unlink does not disturb the open mapping.