Fault-tolerant workflow engine that survives server restarts and crashes. Build long-running business processes that never lose state.
Every step is persisted to the database. Resume from exactly where you left off.
Sleep for days, weeks, or months. The server can restart without losing progress.
Failed steps are automatically retried with exponential backoff.
Survives crashes, restarts, and deployments. Your workflows always complete.
Standard code fails if the server restarts in the middle of execution. Canx Flow persists the execution state to the database after every step. If the server crashes, it resumes automatically from the last successful step.
Create workflows using the workflow() function. Each step is persisted and can be resumed if interrupted.
1import { workflow } from 'canxjs';23const subscriptionFlow = workflow('subscription', async (ctx, userId) => {45// Step 1: Charge6await ctx.step('charge', () => payment.charge(userId));78// Step 2: Sleep (Durable)9// Server can be offline during this time10await ctx.sleep('trial', 30 * 24 * 3600 * 1000); // 30 days1112// Step 3: Renew13await ctx.step('renew', () => payment.renew(userId));1415});
Start workflows asynchronously and manage their lifecycle. Check status, cancel, or retry as needed.
1// Start async (returns workflow ID)2const id = await subscriptionFlow.start('user-123');34// Check status5const status = await subscriptionFlow.status(id);6// { state: 'sleeping', step: 'trial', resumeAt: '2024-03-15T...' }78// Cancel if needed9await subscriptionFlow.cancel(id);
| Method | Purpose |
|---|---|
| ctx.step(name, fn) | Execute once, cache result |
| ctx.sleep(name, ms) | Durable timer that survives restarts |
| ctx.waitFor(name, event) | Wait for external event |
1const orderFlow = workflow('order-processing', async (ctx, orderId) => {23// Regular step - executed once, result cached4const order = await ctx.step('fetch-order', () => {5return db.orders.find(orderId);6});78// Conditional step9if (order.requiresApproval) {10await ctx.step('wait-approval', () => {11return notifyManager(order);12});1314// Durable sleep - survives restarts15await ctx.sleep('approval-timeout', 24 * 60 * 60 * 1000); // 24h16}1718// Side effect step19await ctx.step('send-confirmation', () => {20return email.send(order.customerEmail, 'Order Confirmed');21});2223});