Workflows

Durable Workflows

Durable workflows with retries, timers, waits, and resumable state right from your own database. Inspired by Cloudflare Workflows, but usable anywhere.

Install

npm install @fragno-dev/workflows @fragno-dev/db

Runtime

Steps + events + timers

Best for

Durable orchestration

Capabilities

Durable steps + retries

Run long-lived workflows with durable state stored in your database.

Timers + event waits

Pause for events, schedule timers, and resume exactly where you left off.

HTTP API + CLI

Create, inspect, and control workflows via HTTP routes and the fragno-wf CLI.

Blueprint

Define the workflow, mount the fragment, start the durable processor.

1. Install

Install the workflows fragment and database package.

npm install @fragno-dev/workflows @fragno-dev/db

2. Define a workflow

Create a workflow with events, timers, and durable steps.

import { defineWorkflow } from "@fragno-dev/workflows";export const ApprovalWorkflow = defineWorkflow(  { name: "approval-workflow" },  async (event, step) => {    const approval = await step.waitForEvent("approval", {      type: "approval",      timeout: "15 min",    });    await step.sleep("cooldown", "2 s");    return { approved: approval.payload?.approved };  },);export const workflows = { approval: ApprovalWorkflow } as const;

3. Create the fragment server

Instantiate the fragment and start durable hook processing.

import { defaultFragnoRuntime, instantiate } from "@fragno-dev/core";import { createDurableHooksProcessor } from "@fragno-dev/db/dispatchers/node";import { workflowsFragmentDefinition, workflowsRoutesFactory } from "@fragno-dev/workflows";const fragment = instantiate(workflowsFragmentDefinition)    .withConfig({ workflows, runtime: defaultFragnoRuntime })  .withRoutes([workflowsRoutesFactory])  .withOptions({ databaseAdapter })  .build();const dispatcher = createDurableHooksProcessor([fragment], { pollIntervalMs: 2000 });dispatcher.startPolling();

Examples

Retry workflow

const RetryWorkflow = defineWorkflow(  { name: "retry-workflow" },  async (_event, step) => {    return await step.do(      "retry-step",      { retries: { limit: 1, delay: "40 ms", backoff: "constant" } },      () => {        if (Math.random() < 0.5) {          throw new Error("RETRY_ME");        }        return { ok: true };      },    );  },);

Use it

CLI

fragno-wf workflows list -b https://host.example.com/api/workflowsfragno-wf instances create -b https://host.example.com/api/workflows -w approvals \  --params '{"requestId":"req_1","amount":125}'fragno-wf instances send-event -b https://host.example.com/api/workflows -w approvals \  -i inst_123 -t approval --payload '{"approved":true}'

HTTP

const baseUrl = "/api/workflows";await fetch(`${baseUrl}/workflows/approval/instances`, {  method: "POST",  headers: { "content-type": "application/json" },  body: JSON.stringify({ requestId: "req_123", amount: 200 }),});await fetch(`${baseUrl}/workflows/approval/instances/inst_123/events`, {  method: "POST",  headers: { "content-type": "application/json" },  body: JSON.stringify({ type: "approval", approved: true }),});

Use cases

Approval chains

Route approvals through humans or systems with auditable history.

Background orchestration

Coordinate retries, timers, and async jobs without glue code.

Customer onboarding

Guide setup steps, wait for external events, then continue automatically.