Skip to content

Snapshots

Create a leased point-in-time namespace view and read consistently from it.

A snapshot is an expiring, read-only view of a namespace. Creating a snapshot reserves the namespace’s current state and returns a snapshot_id; a read that supplies that ID will resolve against the captured state (as long as the lease is live), even as new commits stream in.

Snapshots may be useful for multi-step reads, generating exports, and changefeed consumers that need a fixed view of the namespace.

Creating a snapshot requires a name and a TTL measured from the server’s current time:

{
"name": "nightly-export",
"ttl_ms": 3600000
}

The response includes captured_seq, created_at_ms, and expires_at_ms. (Snapshot names are just labels and do not need to be unique.)

OperationEndpointBehavior
Create snapshotPOST …/snapshotsCaptures the namespace’s current state under a new snapshot_id.
List snapshotsGET …/snapshotsLists live snapshots; deleted and expired snapshots are omitted.
Extend snapshotPOST …/snapshots/{snapshot_id}/extendSets a new TTL from the server’s current time without passing the lifetime ceiling.
Delete snapshotDELETE …/snapshots/{snapshot_id}Removes the snapshot pin. A second delete returns snapshot_not_found.

An extension can move expires_at_ms later (but never beyond snapshot.max_lifetime_ms from the original created_at_ms).

Pass snapshot_id to supported read operations:

ReadSnapshot behavior
Stat a pathReturns the entry as of the snapshot.
Stat an inodeReturns the inode entry as of the snapshot.
List path entriesLists the directory state.
List inode childrenLists the directory state by inode ID.
Get file bytesReads the file revision as of the snapshot.
Create a downloadGrants access to the snapshotted file revision.
List changesLists changes through the snapshot’s greatest sequence.

File-content and download requests cannot combine snapshot_id with revision_no (the snapshot already selects the revision as of the reservation). Similarly, for a snapshot-bounded changefeed, after_seq cannot be greater than the captured sequence.

Snapshot reads require a live lease. LoonFS never silently falls back to the current namespace:

Error codeHTTPMeaning
snapshot_not_found404No checkpoint record exists under that ID, including after deletion.
snapshot_gone410The snapshot lease expired while its pin still exists.
snapshot_quota_exceeded409The namespace already has the maximum number of live snapshots.

Deployments advertise three snapshot limits through capabilities:

LimitMeaning
snapshot.max_ttl_msLargest TTL accepted by create or extend.
snapshot.max_lifetime_msLatest expiry allowed relative to the snapshot’s original creation time.
snapshot.max_live_per_namespaceMaximum live, unexpired snapshots in one namespace.

See the reference server defaults on the Limits page.

All three use durable checkpoint records underneath, with different contracts:

MechanismOwnerLifetimeIntended use
SnapshotApplicationRequired lease, bounded by deployment limitsStable public reads through snapshot_id.
User checkpointOperatorUntil explicit deletion or optional expiryAdministrative pins and external maintenance workflows.
Fork checkpointFork lifecycleWhile the target namespace depends on its source basisInternal copy-on-write namespace ancestry.

Snapshots are deleted through the snapshot API. The maintenance checkpoint deletion operation refuses snapshot- and fork-owned records so one API cannot invalidate another operation’s state. If you’re using ACLs, you need admin permissions to manage snapshots, and read and history permissions to read files from them. See Checkpoints and Namespaces & forking.

Terminal window
loonfs snapshot create demo --name nightly-export --ttl-ms 3600000
loonfs snapshot list demo
loonfs use demo
loonfs snapshot extend demo {snapshot_id} --ttl-ms 3600000
loonfs ls /reports --snapshot-id {snapshot_id}
loonfs get /reports/summary.csv --snapshot-id {snapshot_id}
loonfs changes --snapshot-id {snapshot_id}
loonfs snapshot delete demo {snapshot_id}