A durable execution runtime in Rust for high-consequence systems.

ObzenFlow is durable execution expressed as a typed stream-processing topology. Each stage is a supervised, event-sourced finite-state machine backed by an ordered journal, and the compiler checks every edge connecting them. Together, those journals preserve the facts, decisions, and effect outcomes required to reconstruct, verify, or resume the entire flow.

The ObzenFlow durable execution stack, from typed stage syntax through supervision, journals, replay, and pluggable infrastructure.

Built for high-consequence systems.

A high-consequence system is one where being wrong costs something real. A payment captured twice, an order lost mid-fulfilment, a compliance export that cannot be defended, a model decision nobody can explain. ObzenFlow was built for exactly these systems, and correctness is the constraint the rest of the design bends around.

Order & payment flows

A charge or a shipment must happen exactly once, and the decision trail has to survive the process that made it.

Ledgers & accounts

Balances are folds over facts. Projection and audit derive from the same journal, so disagreement is detectable and repairable.

Compliance pipelines

An export is only as defensible as its provenance. When an export is derived from journaled facts, the journal preserves the causal path that produced it.

Claims processing

Long-running, interruptible, and contested later. Resume protects the work; replay defends the outcome.

Explainable AI inference

When prompts, outputs, and costs are captured as journaled facts, a model-assisted decision can be reconstructed and questioned from the record.

What Is Durable Execution?

The four guarantees of durable execution.

Durable execution is primarily a safety contract. Any framework claiming to provide it owes you four guarantees. They are the foundation on which resilient and correct systems are built.

ObzenFlow’s real value is combining those guarantees with a small typed vocabulary, idiomatic Rust handlers, first-class effects, built-in resilience, sensible integrations, and an operational substrate that ships in the same binary. You build durable software like an application and operate it like a service, without adopting a separate orchestration platform.

Deterministic reconstruction

Journaled inputs rebuild the same state across deterministic and order-certified regions. Verification catches divergence instead of silently accepting it.

Exactly-once effects

Once an effect outcome is committed, reconstruction reuses it instead of calling the dependency again. Non-idempotent calls require a stable key enforced by the receiver.

Durable progress

Progress becomes durable when a fact is committed to the stage journal. If the process dies, ObzenFlow reconstructs the run from those committed facts rather than treating uncommitted work as progress.

Resume over restart

Resume treats an interrupted run as unfinished rather than failed. The same run continues from its journals, finished work untouched, and one command drives it the rest of the way to done.

Durable execution without infrastructure lock‑in or coupling.

ObzenFlow’s journal is a port in the domain core, not a dependency on a disk format, database, or storage SDK. The built-in disk implementation provides durable execution from a single binary, while another backend can implement the same contract without changing how runs are reconstructed, replayed, or resumed. Rust and Cargo enforce that boundary, keeping correctness independent of the infrastructure that stores the journal.

Show me the code

ObzenFlow combines a concise DSL for wiring typed stages into a durable graph with ordinary Rust handlers for your business logic. Sketch the flow with placeholders, fill in each stage one at a time, and let ObzenFlow add supervision, journaling, and replay without changing the code inside.

The blueprint

You sketch the whole flow with placeholder handlers, then fill in real logic one stage at a time. Every stage models one business decision and enumerates every outcome.

flow.rs
the blueprint
flow! {
    name: "order_flow",
    journals: disk_journals(journal_root),

    stages: {
        // Sources and sinks take I/O adapter values.
        orders = source!(Order => orders_feed());

        // Logic stages take your handler types.
        validate = transform!(
            Order -> { ValidOrder, RejectedOrder } => Validate
        );

        authorize = effectful_transform!(
            ValidOrder -> { Authorized, Declined } => Authorize,
            effects: [AuthorizePayment with [gateway_resilience]]
        );

        paid = sink!(Authorized => fulfillment());
    },

    topology: {
        orders    |> validate;
        validate  |> authorize;
        authorize |> paid;
    }
}

Everything right of => is a plain Rust value. Validate and Authorize are your handler structs; orders_feed() and fulfillment() build the I/O adapters. The valid path crosses the declared AuthorizePayment effect under gateway_resilience, and the |> block wires the typed stages into the executable graph.

Your handler

The handler classifies each input and returns one of the declared outcomes as a plain Rust value, in the lineage of value-oriented programming.

validate.rs
plain Rust
// A handler is ordinary Rust: a struct, a trait,
// a decision. Unit-test it like any other function.
#[derive(Debug, Clone, StageOutputFacts)]
pub enum ValidationOutcome {
    Valid(ValidOrder),
    Rejected(RejectedOrder),
}

pub struct Validate;

impl TypedTransformHandler for Validate {
    type Input = Order;
    type Output = ValidationOutcome;

    fn process(&self, order: Order)
        -> Result<Self::Output, HandlerError>
    {
        if order.amount_cents == 0 {
            return Ok(ValidationOutcome::Rejected(RejectedOrder {
                order_id: order.order_id,
                reason: RejectionReason::ZeroAmount,
            }));
        }
        Ok(ValidationOutcome::Valid(ValidOrder::from(order)))
    }
}

This is the Validate the blueprint names. ObzenFlow wraps supervision, journaling, and replay around it at runtime, and a plain #[test] exercises it without any of them.

Build a durable workflow in Rust, step by step.

Follow one runnable payment example from a typed placeholder sketch through declared effects, journaled facts, verified replay, and safe resume.