Open sourceRust, TypeScript, Python, Go and Java1.0.0
Fusee: durable execution at the speed of the disk
Fusee is an open-source durable execution engine. You write a long-running process as ordinary async code, with steps, sleeps, signals and child workflows. If the machine dies halfway through, the process carries on from where it stopped.
In a chain of Rust steps on an AWS i8g.2xlarge with local NVMe, the median step took 14 µs. A durable write on the same drive took 12 µs. Fusee is a library, so there’s no orchestrator, database or queue between your code and the disk.
A workflow is a function
Every call through ctx is journaled: steps, sleeps, signals, child workflows, even the current time and random numbers. After a crash, the function runs again from the top and the journal hands back what already happened, so finished steps don’t run twice.
A step has a stable key across retries. Pass it to a payment service as an idempotency key to avoid charging twice after a crash.
- import { Engine, signal, workflow } from "@bitsinfra/fusee";
- const review = signal<boolean>("review");
- const checkout = workflow("checkout", async (ctx, order: Order) => {
- const quote = await ctx.step("quote", () => pricing.quote(order));
- const charge = await ctx.step("charge", (s) => payments.charge(quote, { idempotencyKey: s.key, signal: s.signal }), {
- retry: { attempts: 5, max: "1m" },
- });
- await ctx.sleep("cool-off", "10m");
- const approved = await ctx.waitFor(review, { timeout: "1d" });
- return approved ? charge.id : await ctx.step("refund", () => payments.refund(charge.id));
- });
- const engine = await Engine.open({ dir: "./data", workflows: [checkout] });
- const run = await engine.start(checkout, "order-123", order);
- await run.signal(review, true);
- console.log(await run.result());
- use fusee::{Config, Ctx, Engine, RetryPolicy, Signal, WorkflowRef};
- use std::time::Duration;
- const CHECKOUT: WorkflowRef<Order, String> = WorkflowRef::new("checkout");
- const REVIEW: Signal<bool> = Signal::new("review");
- let engine = Engine::open(Config::local("./data")).await?;
- engine.register(CHECKOUT, |ctx: Ctx, order: Order| async move {
- let quote: Quote = ctx.step("quote", || pricing::quote(&order)).await?;
- let charge: Charge = ctx
- .step("charge", || payments::charge("e, ctx.key()))
- .retry(RetryPolicy::attempts(5))
- .await?;
- ctx.sleep("cool-off", Duration::from_secs(600)).await?;
- match ctx.wait_for(REVIEW).timeout(Duration::from_secs(86_400)).await? {
- Some(true) => Ok(charge.id),
- _ => ctx.step("refund", || payments::refund(&charge)).await,
- }
- });
- let run = engine.start(CHECKOUT, "order-123", &order).await?;
- run.signal(REVIEW, &true).await?;
- println!("{}", run.result().await?);
- import fusee
- review = fusee.signal("review", bool)
- @fusee.workflow("checkout")
- async def checkout(ctx: fusee.Ctx, order: Order) -> str:
- quote = await ctx.step("quote", lambda: pricing.quote(order))
- charge = await ctx.step("charge", lambda s: payments.charge(quote, key=s.key), retry=fusee.Retry(attempts=5))
- await ctx.sleep("cool-off", "10m")
- approved = await ctx.wait_for(review, timeout="1d")
- return charge["id"] if approved else await ctx.step("refund", lambda: payments.refund(charge))
- engine = await fusee.Engine.open("./data", workflows=[checkout])
- run = await engine.start(checkout, "order-123", order)
- await run.signal(review, True)
- print(await run.result())
The TypeScript SDK on npm and the Python SDK on PyPI include the Fusee CLI. Rust users can install the CLI with cargo install --locked fusee-cli from crates.io.
npm install @bitsinfra/fuseeWhat a step costs
Recording a step’s result durably is the whole job of a durable execution engine. Published figures put it at about a millisecond to a few hundred milliseconds per step. One flush on a datacenter drive takes about ten microseconds.
Fusee spends a step’s time where it has to: on the disk.
Activity completion at p50, Temporal’s benchmark, May 2024
Median per step on a three-node cluster, Restate’s measurements
Per step, DBOS’s own figure
Rust local, sequential steps at p50 on an AWS i8g.2xlarge with local NVMe
One fdatasync on an Intel D7-P5520 with power-loss protection, Small Datum, January 2026
What it promises
Acknowledged starts, signals and step results survive the failures covered by the selected durability mode.
A recorded step result never changes, and the code after it sees the same value on every run.
A step’s function runs at least once, and again only if the process failed before its result was durable. At services that honor idempotency keys, reuse the step’s key so the effect happens once.
Nothing leaves the process based on state a crash could take back.
These are the journaling semantics of DBOS, Restate and Temporal activities. Fusee doesn’t weaken them anywhere; it changes what they cost.
Why it’s fast
No distance
Fusee is a library. Workflows run in your process and the engine writes a log beside them. A step never crosses a network to an orchestrator, waits on a database transaction or sits in a queue.
Code runs ahead of the disk
Appending a record makes it visible at once. Only two things wait for the disk: a step’s function, for the records before it, and anything that leaves the process. Everything in between runs while the write is in flight.
One flush in flight
No timer and no batching window. Each flush takes everything appended since the last one, so an idle engine writes a lone record at once and a busy one carries more records in every write.
One log per drive
Every shard appends to one shared log, written with direct I/O. The drive sees a single stream of writes, never more than two deep, instead of one queue per core.
From one process to three machines
The same engine runs three ways, chosen when you open it.
| Mode | Outputs wait for | Survives |
|---|---|---|
| Local | A flush on this machine | A process crash, and power loss on drives that honor flushes |
| Server | A flush on the server, one round trip away | Any worker’s crash: another worker takes over its shards |
| Replicated | A quorum, two of three or three of five | Losing a minority of the machines |
Server mode puts the log in a process of its own and lets many workers share it, over shared memory on one host or TCP across hosts. Shards are leased one at a time, so a worker that hangs loses only its own.
On a cloud, replicated mode is the one we’d run in production. A quorum of local NVMe drives on three machines nearby is faster than one flush on a network volume, and it survives losing a machine.
Everything a workflow engine needs
The five SDKs share the same workflow operations. Fusee records their results in the journal and reuses them during replay.
- Signals and timers
- Durable sleeps, signals with timeouts, and messages between workflows.
- Child workflows
- With ID and close policies, plus
allandrace. - Queries
- Read a workflow’s state. The answer waits until what it read is durable.
- Updates
- Validated, accepted once and answered from the journal, with update-with-start.
- Retries, timeouts and heartbeats
- Backoff per step, timeouts per step and per workflow, heartbeats for long steps.
- Async completion
- Finish a step later with a token, for approvals and callbacks.
- Versions and patches
- Runs finish on the code they started with; a patch reaches a sleeping workflow where its code meets it.
- Replay testing
- Export recent journals and replay new code against them in CI before you deploy.
- Schedules
- Cron with time zones, overlap rules and backfill, built on durable timers.
- Limits
- Concurrency and rate limits that never hand out an extra permit, even across crashes.
- Read-only steps
- Lookups and model calls that run without waiting for the disk.
- Encryption
- AES-256-GCM payloads, so logs, servers and replicas hold only ciphertext.
- Search
- Search attributes and filtered listing of runs.
- Cancellation
- Cancel with compensation, terminate and reset, continue-as-new.
- Operations
- OpenTelemetry, a web UI over every run and its journal, TLS, and continuous backup to object storage.
- Simulation
- Run your own workflows under Fusee’s seeded simulator, with skipped time and injected crashes and disk faults.
Get started
Fusee is open source under the MIT or Apache 2.0 license, and sends no telemetry. Version 1.0.0 is the first stable release.