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.
git clone https://github.com/majiayu000/claude-skill-registry
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"
skills/data/cloudflare-workflows/SKILL.mdCloudflare Workflows
Status: Production Ready ✅ | Last Verified: 2025-12-27 | Version: 3.0.0
Dependencies: cloudflare-worker-base (for Worker setup)
Contents: Quick Start • Commands • Agents • Core Concepts • Critical Rules • Top Errors • Common Patterns • When to Load References • Limits
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:
| Command | Description | Use When |
|---|---|---|
| Complete wizard for new workflow projects | Starting new project, need full setup |
| Quick scaffolding for workflow classes | Adding workflow to existing project |
| Interactive debugging with error patterns | Troubleshooting workflow issues |
| Test workflows locally and remotely | Validating 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:
| Agent | Description | Triggers |
|---|---|---|
| Auto-detects and fixes configuration/runtime errors | "debug workflow", "fix workflow errors" |
| Analyzes performance, cost, and reliability | "optimize workflow", "improve performance" |
| 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:
| Script | Purpose |
|---|---|
| Validate wrangler.jsonc configuration |
| Create and test workflow instances |
| Measure performance and cost |
| Scaffold new workflows from templates |
| 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:
: Environment bindings (KV, D1, etc.)Env
: Typed payload passed when creating workflow instanceParams
: Containsevent
,id
,payloadtimestamp
: Methods for durable executionstep
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
for complete exampletemplates/basic-workflow.ts
Scheduled Workflow
Workflow with time delays between steps using
step.sleep() or step.sleepUntil().
Use cases: Reminder sequences, scheduled tasks, delayed notifications
Load
for complete exampletemplates/scheduled-workflow.ts
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
for complete exampletemplates/workflow-with-events.ts
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
for complete example with retry configurationtemplates/workflow-with-retries.ts
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
for complete Worker trigger example
Load templates/worker-trigger.ts
for complete Cron trigger exampletemplates/scheduled-workflow.ts
When to Load References
: Encountering I/O context, serialization, NonRetryableError, event naming, or timeout errors; troubleshooting workflow failures.references/common-issues.md
: Building complex orchestration, approval workflows, idempotency patterns, or circuit breaker patterns.references/workflow-patterns.md
: Need CLI commands for managing workflow instances, debugging stuck workflows, or monitoring production.references/wrangler-commands.md
: Preparing for deployment, need pre-deployment verification, setting up monitoring/error handling.references/production-checklist.md
: Hitting instance/step/payload limits, optimizing for cost, designing high-volume workflows.references/limits-quotas.md
: Using events system, enhanced retries, instance lifecycle control, or latest Workflows features.references/2025-features.md
: Setting up monitoring, custom metrics, external logging integration, or workflow dashboards.references/metrics-analytics.md
: Complex debugging scenarios, stuck instances, systematic diagnosis, performance issues.references/troubleshooting.md
: 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)templates/
Wrangler Commands
Key Commands:
wrangler workflows create, wrangler workflows instances list/describe/terminate, wrangler deploy
Load
for complete CLI reference with all workflow management commands, monitoring workflows, and debugging stuck instances.references/wrangler-commands.md
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
| Resource | Limit |
|---|---|
| Step CPU Time | 30 seconds |
| Workflow Duration | 30 days |
| Step Payload Size | 128 KB |
| Workflow Payload Size | 128 KB |
| Steps per Workflow | 1,000 |
| Concurrent Instances | 1,000 per workflow |
| Event Payload Size | 128 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
for complete checklist with detailed explanations, code examples, verification steps, and deployment workflow.references/production-checklist.md
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/