Skip to content
Menu

Documentation

Guarantees and labels

Sandloom's guarantees are the product: a write commits with its events, a redelivered event is applied once, a retried command does not repeat. But a guarantee holds only under conditions: the right store, a long enough dedupe window, a durable bus. So Sandloom never labels an effect unconditionally. It derives each effect's label from the mechanism that implements it, the configured provider and its windows, and shows a label only where it deviates from the default.

The vocabulary

A label has a delivery part and a visibility part.

Term Meaning
atomic the effect commits if and only if the change that caused it commits
no_loss once the change committed, the effect eventually happens
no_dup the effect happens at most once, even under retries and redelivery
immediate visible to the next read
eventual visible after a delay (a consumer, a projection)

atomic implies no_loss and no_dup. Labels combine by meet: delivery sets intersect and visibility takes the weaker, so a chain of effects is as strong as its weakest link. Response replay (an idempotent HTTP retry) is a separate axis, described in Route policy.

Labels per effect

Effect no_dup when no_loss when atomic when Visibility
a write in the route's write store always always always immediate
an outbox event (its delivery) never: delivery is at-least-once, consumers dedupe on the envelope id the outbox and a durable bus; a delivery may be parked in the dead-letter queue the intent only eventual
a consumer effect with durable=True the inbox is in the same database as the effect, and inbox retention is at least stream retention plus one day the outbox and a durable bus, always qualified: dead_letter=True parks on poison or after the delivery budget; dead_letter=False parks only on an explicit PoisonEventError no eventual
a consumer effect in another store the target write is conditional (version-guarded, see Projections) as above no eventual
a command the provider has a durable command log and its dedupe TTL covers the caller's retry horizon; the cache fallback gives no no_dup (not crash-safe) the caller retries with the same key until a definite answer no immediate
an on_commit callback always never (a crash after the commit loses it) no none
a write in an opted-out secondary (allow_multi_db_write) a keyed or version-guarded write never never immediate

Read the table as "this effect has this property when the condition holds". The conditions are checked where they can be:

  • Guarantee windows are checked at startup: the command dedupe TTL against the relay horizon, the inbox retention against the stream retention. A window that does not hold is a named, accepted risk, refused in production unless listed in SANDLOOM_ACCEPTED_RISKS (ADR-0006, configuration tiers).
  • Features the defaults need (a durable command log, conditional writes) are checked at boot.
  • The write store of a route is inferred statically, so the durable idempotency record, the audit rows and the outbox rows land in the same database as the write (Write admission).

What a module author relies on

  • Your route's write, its events (as intents), its audit rows and its idempotency record commit together or not at all.
  • An event you publish is delivered at least once, in no particular order; every consumer must tolerate a duplicate and an out-of-order event (Events).
  • A consumer with durable=True applies each event once, if its effect is in the consumer's own database.
  • A command call is deduplicated by its key in the provider; it is not atomic with your unit. Compose commands that must undo each other as a saga (Sagas).
  • A projection is eventually consistent and converges (Projections).
  • An on_commit callback can be lost on a crash: never put an effect there that must happen.
The ledger

Every guarantee Sandloom promises and every capability a user relies on is an entry with a stable id (G-... for guarantees, C-... for capabilities) and the tests, sandloom check rules and import contracts that prove it. The ledger (guarantees.yml) is a CI gate: an enforcing test that disappears, an entry without enforcement and not recorded as a gap, or an ADR section without ledger ids fails the build. Soundness scenarios exist for every row of the table above, including the cache fallback and the expired-window cases (C-MSTORE-03).

The page: Guarantees & capabilities.

Design rationale