Durable workflows without the distributed-systems tax

Making asynchronous code reliable usually means adopting message queues, retry frameworks, and persistence layers—infrastructure that often takes longer to wire up than the business logic itself. The open source Workflow Development Kit (WDK) takes a different route: it adds durability as a language-level concept in TypeScript, letting functions pause for minutes or months, survive crashes and deployments, and resume exactly where they stopped—on any framework, platform, or runtime.

Two directives replace queue and retry plumbing

WDK centers on two simple directives that transform ordinary async functions into durable workflows. The use workflow directive marks a function as a durable workflow:

export async function hailRide(requestId: string) {

"use workflow";

const request = await validateRideRequest(requestId);

const trip = await assignDriver(request);

const confirmation = await notifyRider(trip);

const receipt = await createReceipt(trip);

return receipt;

}

That example coordinates a ride-hailing flow. The workflow calls four step functions, each defined with use step, which designates a unit of work that automatically persists progress and retries on failure:

async function validateRideRequest(requestId: string) {

"use step";

// Validate the ride request and get rider details

const response = await fetch(`https://api.example.com/rides/${requestId}`);

// If this fetch fails, the step will automatically retry

if (!response.ok) throw new Error("Ride request validation failed");

const request = await response.json();

return { rider: request.rider, pickup: request.pickup };

}

async function assignDriver(request: any) {

"use step";

// Assign the nearest available driver

}

async function notifyRider(trip: any) {

"use step";

// Notify the rider their driver is on the way

}

async function createReceipt(trip: any) {

"use step";

// Generate a receipt for the trip

}

Each step runs in isolation and retries on failure. In the sample, the first step validates a ride request against an external API; subsequent steps assign a driver, notify the rider, and generate a receipt.

WDK compiles each step into an isolated API route, recording inputs and outputs so execution can be replayed deterministically after a deploy or crash. While a step executes on its separate route, the workflow is suspended without consuming resources; when the step finishes, the workflow resumes automatically at the exact point it left off.

That suspension model means workflows can pause for extended periods. A loyalty reward can wait three days before being issued, with no resource consumption and no state loss:

import { sleep } from "workflow";

export async function offerLoyaltyReward(riderId: string) {

"use workflow";

// Wait three days before issuing a loyalty credit

await sleep("3d"); // No resources are used during sleep

return { riderId, reward: "Ride Credit" };

}

WDK stays close to everyday JavaScript semantics—async/await works as it does today, with no YAML, state machines, or new orchestration syntax to learn. Rather than wiring up queues or schedulers, developers declare how logic should behave and the framework handles the rest.

Webhook-based waiting

Workflows frequently need to stop until external data arrives—a payment confirmation, user action, or third-party response. WDK supports this via webhooks: a workflow can pause until an incoming request hits its endpoint, then resume automatically. No polling, no message queues, no manual state management.

import { createWebhook, fetch } from "workflow";

export async function validatePaymentMethod(rideId: string) {

"use workflow";

const webhook = createWebhook();

// Trigger external payment validation with callback to webhook URL

await fetch("https://api.example-payments.com/validate-method", {

method: "POST",

body: JSON.stringify({ rideId, callback: webhook.url }),

});

// Wait for payment provider to confirm via webhook

const { request } = await webhook;

const confirmation = await request.json();

return { rideId, status: confirmation.status };

}

The webhook flow above sends a callback URL to a payment provider, waits for validation, and resumes once the confirmation lands.

Full observability as a default behavior

Everything inside a workflow—every step, input, output, pause, and error—is recorded in an event log from trigger to final result. That data is surfaced through the API, and also visually through a bundled CLI and Web UI, enabling real-time run tracking, failure tracing, and performance analysis without extra instrumentation.

Vercel automatically detects when a function is durable and dynamically provisions the ideal infrastructure to support it in real time. Vercel automatically detects when a function is durable and dynamically provisions the ideal infrastructure to support it in real time. Vercel automatically detects when a function is durable and dynamically provisions the ideal infrastructure to support it in real time. Vercel automatically detects when a function is durable and dynamically provisions the ideal infrastructure to support it in real time.

Portability via Worlds

WDK is built to run on any platform, framework, and runtime. Each execution environment—called a World—defines how orchestration, persistence, and execution are handled, keeping workflow code portable across clouds and runtimes unchanged.

In local development, the Local World supplies virtual infrastructure, so workflows run without provisioning queues or databases. In production, the Vercel World relies on Framework-defined infrastructure (FdI) to automatically configure persistence, queues, and routing. The same code behaves identically in both environments.

Worlds are extensible. Developers can implement custom Worlds for other runtimes or providers; a reference Postgres World is published on GitHub, and community Worlds exist for databases like Jazz. Consistent with Vercel's Open SDKs philosophy, there is no vendor lock-in.

Where durability matters most

WDK targets systems that need both intelligence and reliability: AI agents reasoning across long contexts that must pause between API calls, RAG pipelines ingesting and embedding data over multi-hour runs without losing progress on a crash, and commerce flows waiting days for user confirmations without holding resources.

By extending JavaScript with durability semantics, WDK removes a major obstacle to reliability in modern applications—letting developers write async code that is durable locally and at scale on Vercel, without the surrounding infrastructure work.