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.

Verified against strata-core@v1.2.7 · Edit this page · Report an issue

agents: this page as markdown → /docs/learn/databases-and-storage.md