Claude-skill-registry cloudflare-workflows

Cloudflare Workflows for durable long-running execution. Use for multi-step workflows, retries, state persistence, or encountering NonRetryableError, execution failed errors.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/cloudflare-workflows" ~/.claude/skills/majiayu000-claude-skill-registry-cloudflare-workflows-8c344b && rm -rf "$T"
manifest: skills/data/cloudflare-workflows/SKILL.md
source content

Cloudflare Workflows

Status: Production Ready ✅ | Last Verified: 2025-12-27 | Version: 3.0.0

Dependencies: cloudflare-worker-base (for Worker setup)

Contents: Quick StartCommandsAgentsCore ConceptsCritical RulesTop ErrorsCommon PatternsWhen to Load ReferencesLimits


Quick Start (10 Minutes)

1. Create a Workflow

Use the Cloudflare Workflows starter template:

npm create cloudflare@latest my-workflow -- --template cloudflare/workflows-starter --git --deploy false
cd my-workflow

What you get:

  • WorkflowEntrypoint class template
  • Worker to trigger workflows
  • Complete wrangler.jsonc configuration

2. Basic Workflow Structure

src/index.ts:

import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers';

type Env = {
  MY_WORKFLOW: Workflow;
};

type Params = {
  userId: string;
  email: string;
};

export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
  async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
    const { userId, email } = event.payload;

    // Step 1: Do work with automatic retries
    const result = await step.do('process user', async () => {
      return { processed: true, userId };
    });

    // Step 2: Wait before next step
    await step.sleep('wait 1 hour', '1 hour');

    // Step 3: Continue workflow
    await step.do('send email', async () => {
      return { sent: true, email };
    });

    return { completed: true, userId };
  }
}

// Worker to trigger workflow
export default {
  async fetch(req: Request, env: Env): Promise<Response> {
    const instance = await env.MY_WORKFLOW.create({
      params: { userId: '123', email: 'user@example.com' }
    });

    return Response.json({
      id: instance.id,
      status: await instance.status()
    });
  }
};

Template: See

templates/basic-workflow.ts
for complete example

3. Configure wrangler.jsonc

{
  "name": "my-workflow",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-22",
  "workflows": [
    {
      "binding": "MY_WORKFLOW",
      "name": "my-workflow",
      "class_name": "MyWorkflow"
    }
  ]
}

Template: See

templates/wrangler-workflows-config.jsonc

4. Deploy

npm run deploy

Commands

Interactive slash commands for workflow development:

CommandDescriptionUse When
/workflow-setup
Complete wizard for new workflow projectsStarting new project, need full setup
/workflow-create
Quick scaffolding for workflow classesAdding workflow to existing project
/workflow-debug
Interactive debugging with error patternsTroubleshooting workflow issues
/workflow-test
Test workflows locally and remotelyValidating workflow behavior

Example Usage:

/workflow-setup   # Full guided setup wizard
/workflow-create  # Quick workflow scaffolding
/workflow-debug   # Debug workflow issues
/workflow-test    # Test workflow execution

Agents

Autonomous agents for complex workflow tasks:

AgentDescriptionTriggers
workflow-debugger
Auto-detects and fixes configuration/runtime errors"debug workflow", "fix workflow errors"
workflow-optimizer
Analyzes performance, cost, and reliability"optimize workflow", "improve performance"
workflow-setup-assistant
Autonomous project scaffolding"setup workflow", "create first workflow"

Key Capabilities:

  • Debugger: 6-phase analysis, auto-fix for I/O context, serialization, export issues
  • Optimizer: Cost analysis, reliability scoring, actionable recommendations
  • Setup Assistant: Project detection, automatic scaffolding, validation

Scripts

Automation scripts in

scripts/
directory:

ScriptPurpose
validate-workflow-config.sh
Validate wrangler.jsonc configuration
test-workflow.sh
Create and test workflow instances
benchmark-workflow.sh
Measure performance and cost
generate-workflow.sh
Scaffold new workflows from templates
check-workflow-limits.sh
Validate against Cloudflare limits

Usage:

./scripts/validate-workflow-config.sh           # Check config
./scripts/test-workflow.sh my-workflow          # Test workflow
./scripts/benchmark-workflow.sh my-workflow 10  # Benchmark 10 runs
./scripts/generate-workflow.sh MyWorkflow       # Generate scaffold
./scripts/check-workflow-limits.sh src/workflows/my-workflow.ts

Core Concepts

WorkflowEntrypoint

Every workflow must extend

WorkflowEntrypoint
:

export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
  async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
    // Workflow logic here
  }
}

Key Points:

  • Env
    : Environment bindings (KV, D1, etc.)
  • Params
    : Typed payload passed when creating workflow instance
  • event
    : Contains
    id
    ,
    payload
    ,
    timestamp
  • step
    : Methods for durable execution

Step Methods

All workflow work MUST be done in steps for durability:

// step.do - Execute work with automatic retries
await step.do('step name', async () => {
  return { result: 'data' };
});

// step.sleep - Wait for duration
await step.sleep('wait', '1 hour');

// step.sleepUntil - Wait until timestamp
await step.sleepUntil('wait until', Date.now() + 3600000);

// step.waitForEvent - Wait for external event
const event = await step.waitForEvent('payment received', 'payment.completed', {
  timeout: '30 minutes'
});

CRITICAL: All I/O (fetch, KV, D1, R2) must happen inside

step.do()
callbacks!

Reference: See

references/workflow-patterns.md
for all patterns


Critical Rules

Always Do ✅

Perform all I/O inside step.do() - Required for durability ✅ Use named steps - Makes debugging easier ✅ Return JSON-serializable data from steps - Required for state persistence ✅ Use step.sleep() for delays - Don't use setTimeout() ✅ Handle errors explicitly - Use try/catch in step callbacks ✅ Use NonRetryableError for permanent failures - Stops retries

Workflow Patterns: See

references/workflow-patterns.md
for:

  • Sequential workflows
  • Parallel execution
  • Event-driven workflows
  • Scheduled workflows
  • Human-in-the-loop workflows

Never Do ❌

Never do I/O outside step.do() - Will fail with "I/O context" error ❌ Never use setTimeout() or setInterval() - Use step.sleep() instead ❌ Never return non-serializable data - Functions, Promises, etc. will fail ❌ Never hardcode timeouts - Use workflow config ❌ Never ignore NonRetryableError - Indicates permanent failure


Top 5 Critical Errors

Error #1: I/O Context Error ⚠️

Error:

Cannot perform I/O on behalf of a different request

Cause: Performing I/O outside

step.do()
callback

Solution:

// ❌ WRONG
const data = await fetch('https://api.example.com');
await step.do('use data', async () => {
  return data; // Error!
});

// ✅ CORRECT
const data = await step.do('fetch data', async () => {
  const response = await fetch('https://api.example.com');
  return await response.json();
});

Error #2: Serialization Error

Error:

Cannot serialize workflow state

Cause: Returning non-JSON-serializable data from step

Solution:

// ❌ WRONG
await step.do('process', async () => {
  return { fn: () => {} }; // Functions not serializable
});

// ✅ CORRECT
await step.do('process', async () => {
  return { result: 'data' }; // JSON-serializable
});

Error #3: NonRetryableError Not Thrown

Error: Workflow retries forever on permanent failures

Solution:

import { NonRetryableError } from 'cloudflare:workers';

await step.do('validate', async () => {
  if (!isValid) {
    throw new NonRetryableError('Invalid input'); // Stop retries
  }
  return { valid: true };
});

Error #4: WorkflowEvent Not Found

Error:

WorkflowEvent 'payment.completed' not found

Cause: Event name mismatch between

waitForEvent
and trigger

Solution:

// Workflow waits for event
const event = await step.waitForEvent('wait payment', 'payment.completed', {
  timeout: '30 minutes'
});

// Trigger event with EXACT same name
await instance.trigger('payment.completed', { amount: 100 });

Error #5: Workflow Execution Failed

Error:

Workflow execution failed: Step timeout exceeded

Cause: Step exceeds maximum CPU time (30 seconds)

Solution:

// ❌ WRONG
await step.do('long task', async () => {
  for (let i = 0; i < 1000000; i++) {
    // Long computation
  }
});

// ✅ CORRECT - Break into smaller steps
for (let i = 0; i < 100; i++) {
  await step.do(`batch ${i}`, async () => {
    // Process batch
  });
}

All Issues: See

references/common-issues.md
for complete documentation


Common Patterns

Sequential Workflow

Basic workflow with steps executing in order. Each step completes before the next begins.

Use cases: Order processing, user onboarding, data pipelines

Load

templates/basic-workflow.ts
for complete example

Scheduled Workflow

Workflow with time delays between steps using

step.sleep()
or
step.sleepUntil()
.

Use cases: Reminder sequences, scheduled tasks, delayed notifications

Load

templates/scheduled-workflow.ts
for complete example

Event-Driven Workflow

Wait for external events with

step.waitForEvent()
. Always set timeout and handle with
NonRetryableError
:

const payment = await step.waitForEvent('wait payment', 'payment.completed', {
  timeout: '30 minutes'
});
if (!payment) throw new NonRetryableError('Payment timeout');

Load

templates/workflow-with-events.ts
for complete example

Workflow with Retries

Use

NonRetryableError
for permanent failures (404), regular
Error
for transient failures (5xx):

const data = await step.do('fetch', async () => {
  const response = await fetch(url);
  if (!response.ok) {
    if (response.status === 404) throw new NonRetryableError('Not found');
    throw new Error('Temporary failure'); // Will retry
  }
  return await response.json();
});

Load

templates/workflow-with-retries.ts
for complete example with retry configuration


Triggering Workflows

From Worker: Create instances via

env.MY_WORKFLOW.create()
, get status with
instance.status()
, trigger events with
instance.trigger()
.

From Cron: Use

scheduled()
handler to create workflow instances on schedule.

Load

templates/worker-trigger.ts
for complete Worker trigger example Load
templates/scheduled-workflow.ts
for complete Cron trigger example


When to Load References

references/common-issues.md
: Encountering I/O context, serialization, NonRetryableError, event naming, or timeout errors; troubleshooting workflow failures.

references/workflow-patterns.md
: Building complex orchestration, approval workflows, idempotency patterns, or circuit breaker patterns.

references/wrangler-commands.md
: Need CLI commands for managing workflow instances, debugging stuck workflows, or monitoring production.

references/production-checklist.md
: Preparing for deployment, need pre-deployment verification, setting up monitoring/error handling.

references/limits-quotas.md
: Hitting instance/step/payload limits, optimizing for cost, designing high-volume workflows.

references/2025-features.md
: Using events system, enhanced retries, instance lifecycle control, or latest Workflows features.

references/metrics-analytics.md
: Setting up monitoring, custom metrics, external logging integration, or workflow dashboards.

references/troubleshooting.md
: Complex debugging scenarios, stuck instances, systematic diagnosis, performance issues.

templates/
: basic-workflow.ts (sequential), scheduled-workflow.ts (delays/sleep), workflow-with-events.ts (waitForEvent), workflow-with-retries.ts (custom retry), worker-trigger.ts (Worker triggers), wrangler-workflows-config.jsonc (Wrangler config), parallel-execution-workflow.ts (batched parallel processing), circuit-breaker-workflow.ts (resilient external calls)


Wrangler Commands

Key Commands:

wrangler workflows create
,
wrangler workflows instances list/describe/terminate
,
wrangler deploy

Load

references/wrangler-commands.md
for complete CLI reference with all workflow management commands, monitoring workflows, and debugging stuck instances.


State Persistence

Workflows automatically persist state between steps. No manual state management needed:

export class StatefulWorkflow extends WorkflowEntrypoint {
  async run(event, step) {
    // Step 1 result is automatically persisted
    const result1 = await step.do('step 1', async () => {
      return { data: 'value' };
    });

    // Even if workflow crashes here, step 1 won't re-run
    await step.sleep('wait', '1 hour');

    // Step 2 can use step 1's result (still available after sleep)
    await step.do('step 2', async () => {
      console.log(result1.data); // 'value' - persisted!
    });
  }
}

Key Points:

  • Step results automatically persisted
  • Completed steps never re-run (even after crash/restart)
  • State available throughout workflow lifetime

Limits

ResourceLimit
Step CPU Time30 seconds
Workflow Duration30 days
Step Payload Size128 KB
Workflow Payload Size128 KB
Steps per Workflow1,000
Concurrent Instances1,000 per workflow
Event Payload Size128 KB

Workarounds:

  • Large data: Store in KV/R2, pass key in step
  • Long CPU: Break into smaller steps
  • Many steps: Consider sub-workflows

Pricing

  • Duration: $0.02 per million GB-s (same as Workers)
  • Requests: $0.15 per million (workflow creation + step execution)
  • State Storage: Included (no additional cost)
  • Sleep: Free (no CPU usage during sleep)

Example Cost (1M workflow runs):

  • 5 steps each = 5M requests = $0.75
  • 10ms per step = 50GB-s = $0.001
  • Total: ~$0.75 per million workflows

Troubleshooting

"I/O context" error

Solution: Move all I/O into

step.do()
callbacks → See
references/common-issues.md
#1

"Serialization error"

Solution: Return only JSON-serializable data from steps → See

references/common-issues.md
#2

Workflow retries forever

Solution: Throw

NonRetryableError
for permanent failures → See
references/common-issues.md
#3

"WorkflowEvent not found"

Solution: Ensure event names match exactly → See

references/common-issues.md
#4

"Step timeout exceeded"

Solution: Break long computations into smaller steps → See

references/common-issues.md
#5


Production Checklist

10-Point Pre-Deployment Checklist: I/O context isolation, JSON serialization, NonRetryableError usage, event name consistency, step duration limits, error handling, retry configuration, timeouts, workflow naming, and monitoring.

Load

references/production-checklist.md
for complete checklist with detailed explanations, code examples, verification steps, and deployment workflow.


Official Documentation

Workflows: https://developers.cloudflare.com/workflows/API Reference: https://developers.cloudflare.com/workflows/reference/Examples: https://developers.cloudflare.com/workflows/examples/Blog: https://blog.cloudflare.com/cloudflare-workflows/