Write ordinary functions - backend jobs or long-running AI agents. durablex saves each step as it runs, so the work survives crashes, restarts, and deploys, retrying and resuming exactly where it left off. Fully managed - no infrastructure to run.
Expose your workflows with serve() and register(), or dial out with connect() over a WebSocket - no inbound URL needed.
Wrap each unit of work in step.run(). The engine saves the result, retries on failure, and resumes from the last checkpoint.
The console streams every run and step. Cancel, pause, resume, or replay - from the console or the REST API.
Each section pairs what you write with the live console view it produces.
Wrap work in a step. Each runs once and its result is saved, so a crash replays to the last checkpoint and continues - it never re-runs what already finished.
const orderCreated = defineWorkflow<{ orderId: string }>({ name: "order.created", retry: { maxAttempts: 3 }, handler: async (ctx) => { const charge = await ctx.step.run("charge", () => chargeCard(ctx.event.data)); await ctx.step.sleep("settle", "10s"); return ctx.step.run("ship", () => createShipment(charge)); },});A workflow starts from an event, optionally gated by a CEL filter, or on a cron schedule with no event at all. Every event is kept in a durable, replayable log.
const proWelcome = defineWorkflow({ name: "welcome.pro", triggers: [{ event: "user.signup", if: 'event.data.plan == "pro"' }], handler: async (ctx) => { /* ... */ },});// a cron trigger needs no event:// triggers: [{ cron: "@every 1m" }]Eight controls live right next to retry on the workflow, enforced by the engine. Pick one to see how it is declared.
A runner exposes your workflows to the engine. Serve mode stands up an HTTP endpoint the engine calls; connect mode dials out over a WebSocket - so an agent behind NAT needs no inbound URL.
Register a runner and the engine reads its workflows automatically - their retry policy, triggers, and flow controls. No manifest to keep in sync.
Every run, step, input, output, and error is live in the embedded dashboard. Cancel, pause, resume, or replay a finished run - from the UI or the same REST endpoints.
import { createClient } from "@durablex/sdk/client";const dx = createClient({ engineUrl: "http://localhost:6770" });await dx.runs.replay(runId); // also: cancel, pause, resumeNo infrastructure to provision - durablex Cloud runs the engine for you.