Databases and storage
A Strata database is a directory. Not a file with a directory beside it, and not a directory you should treat as opaque: an ordinary folder you can list, copy, archive and delete with the tools you already have.
strata ./mydb kv put greeting hello
ls ./mydb
locks manifest meta README.md snapshots wal
It also introduces itself. README.md inside the directory says what the
directory is, so someone who finds it in a backup six months from now does not
have to guess.
What each part is for
snapshots/ holds the committed state. This is the data.
wal/ is the write-ahead log. A commit lands here first, then becomes part
of a snapshot. Durability is about the gap between
those two moments.
manifest/ records which snapshot is current and what branches exist. It is
how a reopened database knows where it left off.
meta/ holds bookkeeping, including how far the log has been consumed.
locks/ holds writer.object@, which is how a second process discovers
that someone already has this database open.
You do not edit any of these by hand. But knowing they exist changes what you can reason about: the database is a directory of ordinary files, so the questions you would ask about any directory of ordinary files have ordinary answers.
A database with no directory
--cache gives you the same engine with nothing on disk:
strata --cache kv put a 1
strata --cache info
target cache
durable false
Nothing is created, anywhere. That is the mode to reach for in tests, in CI, and in the browser, where the same engine compiled to wasm runs the demo on the homepage.
Copying, moving and backing up
A database that nothing has open is a directory, and copying it does what you would expect:
cp -r ./mydb ./mydb-backup
strata ./mydb-backup kv get greeting
hello
The copy is a real database, not a reference to the original. Write to one and
the other does not move. That makes cp, rsync, tar and a filesystem
snapshot all valid ways to back up a Strata database, with one condition: do it
while the database is closed.
Copying a directory that a process is actively writing to copies a moment that may never have existed on its own, because the files are not written atomically with respect to each other. This is the same rule that applies to every embedded database, and the safe sequence is the same one: stop, copy, start.
Two processes, one database
Opening a database that another process already has open does not fail:
strata ./mydb start
In another terminal:
strata ./mydb kv put c 3
strata ./mydb ipc status
created c
hosting true
is_owner false
client_count 1
The second process did not take the lock. It found the owner and asked it to do
the work. --ipc off opts out of that entirely, for a single process that wants
no socket.
Embedded databases covers the brokering model in more detail.
Asking a database about itself
Four commands, in increasing depth:
strata ./mydb describe
strata ./mydb info
strata ./mydb health
strata ./mydb doctor
describe is a one-line summary. info reports the target, the version, the
durability mode and the memory budget. health names each subsystem and whether
it is healthy. doctor checks the installation as well as the database, which
is the one to run when something is wrong and you do not yet know what.
What history costs
Every version of every value is retained. That is the point of the database, and it is not free.
A key rewritten a thousand times keeps a thousand versions, all readable with
--as-of, and the directory grows to match. Measured on 1.2.7, rewriting a
single small key, one process per write:
| versions | data | on disk |
|---|---|---|
| 101 | 14 KB | 76 KB |
| 201 | 24 KB | 88 KB |
| 301 | 35 KB | 96 KB |
| 401 | 45 KB | 108 KB |
The two columns are different questions. Data is what the versions weigh,
about 105 bytes each for a short value, and it is the number admin storage
reports. On disk is what the filesystem hands to du: the same history
plus what the files holding it cost, which here is a flat overhead rather than
something that grows with the history.
Coming from 1.2.6, expect this to look very different. 1.2.6 left one directory
per commit under timeline/ and nearly all of them were empty, so the same 401
versions took 1.7 MB instead of 108 KB
(strata-core#3692,
fixed in 1.2.7). A database written by 1.2.6 is cleaned up the first time 1.2.7
opens it, with nothing to run and no migration step: in that measurement it
went from 1.7 MB to 128 KB on the first open, with every version still there.
What Strata does reclaim, it reclaims by itself. A clean close drains the session’s debt under a bounded budget (unreferenced table objects, quarantined objects and superseded snapshots), then checkpoints and truncates the write-ahead log it covered. Reopening finishes what a previous session left, including after a crash, and a database that goes quiet gets one reclaim pass per quiet period. You do not run anything to make this happen.
What it does not reclaim is history. Every version is still kept, and there
is no CLI command to prune it: no vacuum, no compact, no retention
window. Reclamation is about debt: copies and logs the database no longer
needs, not the versions you wrote.
If bounding history matters for your workload, the ways to do it today are to fork a branch and keep the short one, or to write a fresh database and copy forward what you need. Neither is a retention policy, and it is worth knowing that before you point a high-churn workload at a directory you expect to stay small.
strata ./mydb admin storage --audit breaks the footprint down by family and
tells you what the reclaim runners could still free. See
Inspect database health.
Where to look next
Durability is the other half of this: what a commit has promised you by the time it returns.