Skip to content

Durability Guarantees

A workflow may run for milliseconds, hours, or days. During that time, worker processes can crash, APIs can time out, requests can be delivered twice, and users can disappear.

Invariant's durability model is built around seven execution invariants. These invariants define the contractual guarantees the Runtime preserves regardless of how execution is interrupted.


The 7 Core Invariants

1. Deterministic Transition Evaluation

Problem: If state transitions depend on volatile runtime conditions or unobserved side effects, crash recovery cannot compute identical application state.

Guarantee: Given the exact same compiled workflow graph, initial state, and sequence of events, transition evaluation computes the exact same state update every time.

Mechanism: The execution kernel (ExecutionEngine.transition()) is a pure function. Side effects and model calls are prohibited inside state machine evaluations and must cross explicit capability or reasoning boundaries.


2. Monotonic Event Ordering

Problem: Out-of-order event delivery in asynchronous or concurrent environments can corrupt state machine transitions.

Guarantee: Events targeting a workflow execution (runId) are applied in a strictly increasing, gapless sequence ($1, 2, 3, \dots$).

Mechanism: The storage layer assigns sequence numbers (seq) within transactional locks, enforcing strict event-sourcing consistency per execution.


3. Atomic Transition Persistence

Problem: A crash occurring after updating application state but before recording emitted events or outbox commands leaves the system in a corrupted, half-committed state.

Guarantee: State updates, emitted events, and generated capability outbox intents commit together atomically, or not at all.

$$\text{State Update} + \text{Emitted Events} + \text{Outbox Intents} \implies \text{Single Storage Transaction}$$

Mechanism: RuntimeTransaction commits state mutations and outbox commands within a single database transaction. If the process crashes mid-commit, the entire transaction rolls back cleanly.


4. Recoverable Execution Ownership

Problem: A worker process executing a workflow can crash, freeze, or lose network connectivity mid-execution.

Guarantee: A workflow execution is never permanently stranded because the worker processing it died.

Mechanism: Workers claim executions using expiring leases (worker_id, lease_expires_at). If a worker dies, its lease expires. The Reclaimer Worker safely reclaims ownership from durable storage. While duplicate delivery attempts can occur under network partitions, state transitions and capability idempotency prevent invalid duplicate execution.

text
Worker A claims Run 101  ──►  Worker A dies 💀  ──►  Lease expires  ──►  Worker B reclaims Run 101 from Postgres

5. At-Least-Once Effect Dispatch & Idempotency

Problem: External API calls (like charging a credit card or sending an email) can fail due to network timeouts, leaving uncertainty about whether the external side effect occurred.

Guarantee: External capabilities are dispatched with at-least-once delivery guarantees without executing duplicate side effects on retries.

Mechanism: Capabilities are queued through a transactional Outbox and executed with stable idempotency key formulas (charge:${execution.runId}). External providers receive identical idempotency keys on retries.

ts
capability("issue-refund", {
  idempotencyKey: ({ execution }) => `refund:${execution.runId}`,
  handler: async ({ input }) => {
    return await stripe.refunds.create({ ... }, { idempotencyKey: `refund:${execution.runId}` });
  },
});

6. Durable Reasoning Results

Problem: Re-invoking LLM prompts during crash recovery introduces unexpected latency, high token cost, and non-deterministic response drift.

Guarantee: Once a .reason() node completes and its result is committed, recovery never asks the model to re-evaluate the prompt.

Mechanism: Reasoning results are recorded as durable REASON_COMPLETED events in the event log. During recovery or replay, the kernel reads the committed result directly from storage.


7. Durable Event Re-entry Boundary

Problem: External signals (webhooks, user inputs, timer completions) can be lost if they rely solely on in-memory message channels or transient WebSocket connections.

Guarantee: No external signal or model output mutates workflow state without passing through a durable storage event boundary.

Mechanism: Transient channels (like WebSockets or SSE) are delivery mechanisms for fast-path notifications. Truth always resides in storage. If a connection drops, the event remains queued in storage and resumes execution seamlessly upon reconnection.


The Contractual Guarantee Matrix

InvariantFailure Mode CoveredPreservation Guarantee
1. Deterministic TransitionsVolatile state driftPure, reproducible state machine logic
2. Monotonic Event OrderingRace conditions & out-of-order eventsStrict sequence number ordering per runId
3. Atomic PersistenceMid-commit process crashComplete commit or total rollback
4. Recoverable OwnershipWorker process death (kill -9)Expiring leases & automatic worker reclamation
5. At-Least-Once EffectsNetwork timeout & external API outagesTransactional outbox + stable idempotency keys
6. Durable Reasoning ResultsRecovery prompt re-evaluationRe-reasoning is skipped; cached event result used
7. Durable Re-entry BoundaryConnection drop / SSE disconnectStorage-backed event queues as sole source of truth

Go Deeper

Invariant Durable Execution Engine.