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:
| Concern | Shipped guarantee |
|---|---|
| Signal occurrence and required Flow delivery | Atomic and restart-safe only with a qualifying deployment/store |
| Flow wake | At least once, with stable occurrence and delivery identities |
| Completed Flow steps | Replayed from the durable Flow snapshot |
EffectScopeRef field | JSON-safe snapshot metadata |
| Effect receipts, captures, handlers, ledger | Process-local without a Runtime Effects store; durable records and reverse-plan reconstruction with one. Recovery is application-driven, not worker-driven. |
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.