Skip to content

Runtime & Reliability

The Invariant Runtime is a self-hosted durable execution kernel designed around deterministic transitions, crash recovery, and replayable execution.

"Models reason probabilistically. Infrastructure executes reliably."

The Runtime is the mechanism behind Invariant's durability guarantees. Workflows describe what may happen; the Runtime determines how that execution is persisted, dispatched, recovered, and serialized.


1. Pure Kernel Execution Engine

The Execution Engine (ExecutionEngine) is the pure, deterministic core of Invariant.

ts
export interface ExecutionEngine {
  transition(
    compiledWorkflow: CompiledWorkflow,
    currentState: ExecutionState,
    incomingEvent: StoredRuntimeEvent
  ): TransitionResult;
}
  • Zero API/IO Dependencies: Contains zero database queries, network calls, or system timers.
  • Pure State Transitions: Receives a CompiledWorkflow, current ExecutionState, and an incoming StoredRuntimeEvent, returning a deterministic TransitionResult.
  • Deterministic Replay: Persisted reasoning and capability results can be replayed through the pure kernel.

"Replay re-applies persisted facts through the deterministic transition engine; it does not re-invoke completed model calls or external capabilities."


2. Persistence & Storage Adapter

The Storage Adapter layer persists events, session state, and outbox capability commands.

ts
export type TransitionCommit = {
  runId: string;
  expectedRevision: number;
  events: RuntimeEvent[];
  nextState: ExecutionState;
  commands: OutboxCommand[];
};

export interface RuntimeStore {
  commitTransition(commit: TransitionCommit): Promise<void>;

  loadExecution(runId: string): Promise<DurableExecution | null>;

  loadSession(sessionId: string): Promise<DurableSession | null>;
  saveSession(session: DurableSession): Promise<void>;

  acquireLease(runId: string, workerId: string, ttlMs: number): Promise<Lease | null>;
  renewLease(runId: string, leaseId: string, ttlMs: number): Promise<boolean>;
  releaseLease(runId: string, leaseId: string): Promise<void>;
  findRunnableExecutions(input: { limit: number }): Promise<string[]>;
}

Atomic Transition Commit

A TransitionCommit (state transition, execution events, and outbox capability commands) is persisted atomically within a single database transaction (BEGIN ... COMMIT).


3. Failure, Retry & Fallback Semantics

Every reasoning boundary (.reason()) and capability (.capability()) supports declarative retry policies and deterministic fallback edges. Failure is handled as an explicit, durable fact in the execution graph:

text
external / model failure ──► durable typed fact ──► retry policy ──► deterministic fallback edge

Retry Policy Specification

ts
export interface RetryPolicy {
  maxAttempts: number;    // Total attempts including initial execution (e.g. 3 = 1 initial + 2 retries)
  backoffMs?: number;     // Delay between retries in milliseconds
  retryOn?: string[];     // Specific error codes to retry (e.g. ["MODEL_TIMEOUT", "STRIPE_TIMEOUT"])
}

Deterministic Fallback Edges

When retries are exhausted or an un-retriable error occurs, the boundary failure is persisted as a typed failure event (REASON_FAILED or CAPABILITY_FAILED) and routed through the configured deterministic fallback edge:


4. Outbox & Idempotency Dispatch

External side effects are dispatched durably via the Transactional Outbox Worker. Capability intent is committed atomically before the worker attempts execution:

text
Workflow Transition


 Atomic Commit
 ┌──────────────────────────┐
 │ Execution State          │
 │ Execution Events         │
 │ Capability Intent        │
 └──────────────────────────┘


   Outbox Worker


 Execute Capability

   ┌────┴────┐
 success    failure
   │           │
   ▼           ▼
Result Event   Retry / Failure Event
   │           │
   └─────┬─────┘

   Durable Re-entry

If a worker process crashes after a capability handler succeeds externally but before local completion is committed, the command may be retried.

To make retries safe, capability steps supply stable idempotency keys (payment:${execution.id}) to external APIs across retries.

"Invariant guarantees repeatable intent, not exactly-once effects in systems it does not control."


5. Fast Path & Recovery Path

Invariant coordinates execution dispatch using a dual-path architecture:

The recovery scanner discovers runnable executions (findRunnableExecutions), which includes work with no active lease (e.g. worker died before lease acquisition or lost notification) as well as work with expired leases.

"Notifications improve latency. Durable storage guarantees execution."

Durable Resume after Lease Expiration

Active executions are locked by worker leases. If a worker process dies mid-execution, its lease expires. Background recovery workers discover runnable executions, acquire ownership (acquireLease), load the latest durable execution state and any events required to advance it, and continue execution safely.


6. Serialized Concurrency & Locking

Invariant separates event sequence ordering from execution transition concurrency:

  • Event Ordering (event.seq): Strictly monotonically increasing event sequence numbers (1, 2, 3...) within each run.
  • Transition Concurrency (execution.revision): Optimistic revision check validated atomically during commitTransition():
sql
UPDATE workflow_runs
SET revision = revision + 1
WHERE id = :runId AND revision = :expectedRevision;

If commitTransition() returns 0 rows updated (STALE_TRANSITION), a stale writer cannot commit. The runtime reloads the latest execution state before retrying the transition when policy permits.


Summary Guarantee

"The runtime does not guarantee that external systems never fail. It guarantees that Invariant always knows what was durably committed, what still needs to happen, and how execution may safely continue."

Invariant Durable Execution Engine.