Browse the documentation

Persistence

Snapshot generations, the write-ahead log, data classes and compression.

Where data is stored

Everything NetlyDB persists lives under StorageRoot, a directory you choose. It is resolved once at startup, so two databases in one process cannot share files. The default storage provider is the local file system; see Storage providers.

The write-ahead log

Every write travels one pipeline - admission, a bounded queue, a log sequence number, the apply, and a durable commit. The write-ahead log (WAL) is framed, versioned, checksummed and ordered, and each record carries the identity of the mutation that produced it. Concurrent writers waiting at the same moment share one flush to disk (group commit).

Each collection has one WAL file. It is not segmented or rotated; it is compacted when a new snapshot is published.

Snapshot generations

A snapshot is a generation: it is published atomically next to the previous one, never written over it. Recovery replays the WAL over the last published generation. SnapshotRetention sets how many superseded generations are kept (PreviousGenerations, default 1) and for how long (MaxAge).

Snapshots are per collection. There is no cross-collection point-in-time snapshot.

The write-ahead log and snapshot generations of one collection Write-ahead log (one file per collection) ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓framed · versioned · checksummed · ordered · each record names its mutation publish Generation N-1kept: PreviousGenerations Generation Npublished atomically a new generation sits next to the previous one; nothing is written over After the publish WAL compacted new records append again Recovery = generation N + the log after itreplayed the same way every time
One collection's persistence: a single checksummed log, snapshot generations published side by side, and the log compacted after each publish. Recovery is the last generation plus the log that follows it.

Data classes

How aggressively an unreadable artifact may be discarded and rebuilt depends on how replaceable the data is. DataClasses declares that per collection: Critical, Reconstructable, Regenerable or Disposable. Unclassified collections are treated as Critical, and ambiguity in a critical collection stops writable startup rather than discarding anything.

The four data classes, from least to most replaceable Critical Reconstructable Regenerable Disposable more replaceable; recovery may discard and rebuild an unreadable artifact more readily default for unclassified collections: ambiguity stops writable startup data you can afford to lose
The four data classes order collections by how replaceable their data is, which sets how far recovery may go to rebuild an unreadable artifact.
builder.Services.AddNetlyDB(o =>
{
    o.Durability = DurabilityMode.Synchronous;  // acknowledge after the durable commit (default)
    o.CommitTimeout = TimeSpan.FromSeconds(30); // how long a caller waits for it

    o.SnapshotRetention.PreviousGenerations = 1;      // superseded generations to keep
    o.DataClasses.Default = DataClass.Critical;       // how replaceable this store's data is
});

Compression at rest

Optional, transparent compression of snapshots, the write-ahead log and vector data. It composes with encryption (compress, then encrypt), and reads always decompress automatically, so data stays readable after you turn compression off. File-collection content is always stored compressed.

builder.Services.AddNetlyDB(o =>
{
    o.Compression.Enabled = true;                        // compress new writes at rest
    o.Compression.Algorithm = CompressionAlgorithm.GZip; // or Brotli (smaller, more CPU)
    o.Compression.MinimumSizeBytes = 1024;               // store tiny payloads uncompressed
});

How writes are acknowledged, and what recovery does at startup, is on Durability & recovery.

An unhandled error has occurred. Reload X

Reconnecting

Restoring the connection to the server...

Still trying

Next attempt in seconds

Connection lost

We could not reach the server.