Skip to content
Menu

Documentation

Deduplicate effects

Choose the key for one logical operation and keep it stable across retries. A fresh random key on every attempt creates a new operation.

Boundary Mechanism What to do
Authenticated HTTP write Automatic durable idempotency guard Reuse the same Idempotency-Key; understand status replay in the HTTP guide
Event consumer @on(..., durable=True) (the default) Let the consumer's unit claim the envelope ID; duplicate delivery must not repeat committed effects
Contract command @command(idempotency_key=..., idempotency_scope=...) Declare the operation-key argument and the account scope; callers reuse both
Task or direct command effect A durable inbox claim or a unique operation key in the effect's transaction Atomically claim and write; task redelivery alone is not deduplication
External payment or notification Provider idempotency key plus durable reconciliation Reuse the provider key after timeouts; resolve ambiguous outcomes before compensating

The SDK exposes durable_inbox and operation_key through sandloom.sdk.effects, and the command declaration through sandloom.sdk.contracts. These are advanced tools: choose a scope that cannot collide between unrelated tenants, accounts or operation types.

Keep the claim and the effect together

A consumer's database claim and its database writes commit in the same unit. A rollback leaves the delivery available for retry. A claim committed before an unrelated effect can lose work; an effect committed before its claim can repeat work. Do not add a second dedupe store alongside the framework's model.

For a task, write a regression that delivers the same logical operation twice and checks the stored balance, ledger row or other final effect. For consumers, use deliver(event, times=2) with the same envelope identity, and also check the rollback-and-retry path. The testing reference explains the real consumer runtime and helpers.

Boundaries and retention

At-least-once delivery does not become global exactly-once execution. Different envelope IDs are different deliveries. Outbox retention, inbox retention and command-log TTL must cover the retry horizon; startup checks refuse inconsistent windows. An external provider does not participate in the database transaction. Use an operation intent or a saga when the process crosses those boundaries.