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.