know.2nth.aiTechnologytechcloudflareWorkflows
Technology · Cloudflare · Skill Node

Cloudflare
Workflows.

Durable execution with step.do(). Build multi-step agent flows, payment pipelines, and long-running orchestrations without writing your own retry logic or state machine.

TechnologyDurable ExecutionOpen TierLast updated · Apr 2026

Multi-step execution that survives crashes, restarts, and deploys.

Workflows is Cloudflare's durable execution engine. You define a sequence of steps using step.do(), and the platform guarantees that each step runs exactly once, retries on failure, and persists its result. If the process crashes mid-way, it resumes from the last completed step — not from the beginning.

Think of it as a lightweight alternative to AWS Step Functions or Temporal, but running on Cloudflare's edge with no infrastructure to manage. Each workflow instance is backed by a Durable Object, so state is strongly consistent and the execution model is single-writer.

The primary use case is agent orchestration: multi-step LLM calls, tool invocations, and external API calls that need to survive failures without re-running expensive steps.

Steps, retries, and the run method.

01

Defining a workflow

A workflow is a class with a run() method. Inside it, you call step.do() for each durable step. The name is the checkpoint key — if the workflow restarts, completed steps are skipped and their cached results returned.

# wrangler.toml
name = "order-processor"
main = "src/index.ts"

[[workflows]]
name = "order-flow"
binding = "ORDER_FLOW"
class_name = "OrderWorkflow"
02

step.do() and step.sleep()

Each step.do() call is an atomic unit. If it throws, the workflow retries it with configurable backoff. step.sleep() pauses the workflow for a duration without consuming compute.

import { WorkflowEntrypoint } from "cloudflare:workers";

export class OrderWorkflow extends WorkflowEntrypoint {
  async run(event, step) {
    const validated = await step.do("validate", async () => {
      return validateOrder(event.payload);
    });

    const payment = await step.do("charge", async () => {
      return chargeCard(validated);
    });

    await step.sleep("wait-for-fraud-check", "30 seconds");

    await step.do("fulfil", async () => {
      return shipOrder(payment.orderId);
    });
  }
}
03

Triggering from a Worker

Start a workflow instance from any Worker using the binding. Each instance gets a unique ID and can be queried for status.

export default {
  async fetch(req, env) {
    const order = await req.json();
    const instance = await env.ORDER_FLOW.create({
      params: order,
    });
    return Response.json({ id: instance.id });
  }
};

Where it bites you.

Step names

Step names must be unique per workflow

If two steps share a name, the second returns the cached result of the first. This is a feature for idempotency but a bug if you didn't mean it. Use descriptive, unique step names.

Serialisation

Step return values must be JSON-serialisable

Whatever your step function returns gets persisted. Classes, functions, and Buffers won't survive the round trip. Return plain objects.

Side effects

Code outside step.do() may re-execute

Only code inside a step.do() callback is guaranteed exactly-once. Anything between steps runs again on replay. Put all side effects inside steps.

Concurrency

One instance at a time per ID

Workflows are backed by Durable Objects with single-writer semantics. You can run many instances of the same workflow class, but each instance ID is serialised.

When it fits. When it doesn't.

✓ Use it when
  • Multi-step processes need crash recovery. Payment flows, order processing, onboarding sequences that can't restart from scratch.
  • Agent orchestration with expensive steps. LLM calls, tool invocations, and external APIs where re-running a failed step is cheaper than re-running everything.
  • You want Temporal-like semantics without running Temporal. If you need durable execution but the workload is light enough for the edge, Workflows saves significant ops overhead.

Where this node connects.

Go deeper.