Crux
GuidesDurable ExecutionSignals

Retries, Effects, storage, and Evals

Know what durable Signal delivery preserves, retries, and deliberately refuses to claim.

Delivery is at least once

Durable publication gives each occurrence and required delivery a stable identity. Wake delivery is at least once, so a worker can retry after failure without creating a new occurrence or delivery identity.

Flow replay remains the execution model. Completed named steps reuse their recorded output; code after the wait may run again after a failed attempt. Keep Flow code deterministic, use stable step labels, and make external writes idempotent or model them as Effects.

Consumer failure is isolated to that delivery. It cannot retroactively reject an accepted publication or prevent other required deliveries from proceeding.

Effects and Signal durability stay separate

A Signal-driven resume keeps the Flow's EffectScopeRef consistent across suspension and retry snapshots while the same process still owns the live Effect ledger. That prevents one retry from silently switching to another in-process rollback boundary.

With a Runtime store that implements the Effects port, receipt, scope, unit, attempt, and envelope rows also persist. After restart, the same scope ref reconstructs the reverse recovery plan. Recovery still runs only when your process calls recover(), rollback(), or reconcileEffect() with a matching Runtime program. An external worker that claims and drives Effect recovery after a kill is not part of this release.

A persisted EffectScopeRef is not automatic recovery

The ref is JSON-safe snapshot metadata. Without a Runtime Effects store it cannot reconstruct receipts after process loss. With a store, reconstruction is restart-safe, but recovery is still an explicit API call, not a Signal wake side effect.

Signal durability and Effect recovery therefore answer different questions:

ConcernShipped guarantee
Signal occurrence and required Flow deliveryAtomic and restart-safe only with a qualifying deployment/store
Flow wakeAt least once, with stable occurrence and delivery identities
Completed Flow stepsReplayed from the durable Flow snapshot
EffectScopeRef fieldJSON-safe snapshot metadata
Effect receipts, captures, handlers, ledgerProcess-local without a Runtime Effects store; durable records and reverse-plan reconstruction with one. Recovery is application-driven, not worker-driven.

See Durability and restarts.

Storage owns the durable boundary

The Runtime store owns occurrence records, required delivery records, waiters, events, leases, outbox work, and Flow snapshots. The store must implement these under the exact transaction and durability contract; Core does not import a provider SDK or infer support from an adapter package name.

Payloads and match data must remain JSON-safe. Idempotency state is keyed by a versioned hash, but storage still contains normalized application payloads. Choose retention, access control, encryption, and tenancy boundaries suitable for that data. Do not put credentials or secrets in Signal payloads merely because public errors redact them.

Evals cannot wake durable reactive work

Evals may publish a Signal when no durable binding participates; the receipt is then process-local. If an armed durable Flow wait would receive the occurrence, publication fails before allocation with EVAL_REACTIVE_DISPATCH_FORBIDDEN.

This prevents an Eval case from dispatching real durable application work without an isolated execution/evidence contract. Run end-to-end reactive tests outside Eval execution, using a dedicated namespace and conformant test store.

Next, prepare for operations and errors.

On this page