Ferrite Docs

Key-value Store

Store small durable records with linearizable reads and writes, compare-and-swap, atomic counters, TTL, and ordered prefix scans.

View as Markdown

Ferrite Store is the default home for durable application records. Reads and writes are linearizable, so a successful write is immediately visible to later reads through the authoritative group.

Declare a store

{
  "services": [{ "name": "catalog", "primitive": "store" }],
  "applications": [{
    "name": "catalog-api",
    "artifact_key": "apps/catalog-api@v1",
    "artifact_sha256": "0000000000000000000000000000000000000000000000000000000000000000",
    "bindings": [{ "handle": "catalog", "kind": "store", "service": "catalog" }]
  }]
}

Obtain the handle from AppContext:

let mut catalog = ctx.store("catalog")?;
catalog.put(b"product/coffee", br#"{"name":"Coffee","stock":24}"#).await?;
let product = catalog.get(b"product/coffee").await?;

Choose a key shape

Use stable prefixes such as tenant/{tenant_id}/order/{order_id}. Prefix scans then return related records in key order without a global unbounded query. Include tenant or realm identity in every private key.

Guard concurrent updates

Use compare-and-swap for versioned documents and atomic ADD for counters. A failed comparison means another writer won; reload the record and decide whether to retry the domain action. Do not overwrite blindly after a stale read.

TTL is useful for caches, invitations, and ephemeral views. It is not a substitute for a durable scheduled domain transition; use Cron Jobs when an effect must occur after expiry.

Use Transactions when one decision spans multiple keys, Queues for work, and Object Storage for large values.