cloudflare-workflows
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCloudflare Workflows
Cloudflare Workflows
Workflows provide durable multi-step execution for Workers. Steps persist state, survive restarts, support retries, and can sleep for days.
Workflows 为 Workers 提供持久化的多步骤执行能力。步骤会持久化状态,可在重启后继续运行,支持重试机制,并且可以休眠数天。
Quick Start
快速开始
Create Workflow
创建工作流
typescript
// src/index.ts
import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from "cloudflare:workers";
interface Env {
MY_WORKFLOW: Workflow;
}
interface Params {
userId: string;
action: string;
}
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
const user = await step.do("fetch user", async () => {
const resp = await fetch(`https://api.example.com/users/${event.payload.userId}`);
return resp.json();
});
await step.sleep("wait before processing", "1 hour");
const result = await step.do("process action", async () => {
return { processed: true, user: user.id };
});
return result; // Available in instance.status().output
}
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const instance = await env.MY_WORKFLOW.create({
params: { userId: "123", action: "activate" },
});
return Response.json({ instanceId: instance.id });
},
};typescript
// src/index.ts
import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from "cloudflare:workers";
interface Env {
MY_WORKFLOW: Workflow;
}
interface Params {
userId: string;
action: string;
}
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
const user = await step.do("fetch user", async () => {
const resp = await fetch(`https://api.example.com/users/${event.payload.userId}`);
return resp.json();
});
await step.sleep("wait before processing", "1 hour");
const result = await step.do("process action", async () => {
return { processed: true, user: user.id };
});
return result; // Available in instance.status().output
}
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const instance = await env.MY_WORKFLOW.create({
params: { userId: "123", action: "activate" },
});
return Response.json({ instanceId: instance.id });
},
};wrangler.jsonc
wrangler.jsonc
jsonc
{
"name": "my-workflow-worker",
"main": "src/index.ts",
"workflows": [
{
"name": "my-workflow",
"binding": "MY_WORKFLOW",
"class_name": "MyWorkflow"
}
]
}jsonc
{
"name": "my-workflow-worker",
"main": "src/index.ts",
"workflows": [
{
"name": "my-workflow",
"binding": "MY_WORKFLOW",
"class_name": "MyWorkflow"
}
]
}Deploy
部署
bash
npx wrangler deploybash
npx wrangler deployCore Concepts
核心概念
WorkflowEntrypoint
WorkflowEntrypoint
typescript
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// Workflow logic with steps
return optionalResult;
}
}typescript
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// Workflow logic with steps
return optionalResult;
}
}WorkflowEvent
WorkflowEvent
typescript
interface WorkflowEvent<T> {
payload: Readonly<T>; // Immutable input params
timestamp: Date; // Creation time
instanceId: string; // Unique instance ID
}Warning: Event payload is immutable. Changes are NOT persisted across steps. Return state from steps instead.
typescript
interface WorkflowEvent<T> {
payload: Readonly<T>; // Immutable input params
timestamp: Date; // Creation time
instanceId: string; // Unique instance ID
}警告:事件负载不可变。跨步骤的修改不会被持久化,请通过步骤返回值来传递状态。
WorkflowStep
WorkflowStep
typescript
interface WorkflowStep {
do<T>(name: string, callback: () => Promise<T>): Promise<T>;
do<T>(name: string, config: StepConfig, callback: () => Promise<T>): Promise<T>;
sleep(name: string, duration: Duration): Promise<void>;
sleepUntil(name: string, timestamp: Date | number): Promise<void>;
waitForEvent<T>(name: string, options: WaitOptions): Promise<T>;
}See api.md for full type definitions.
typescript
interface WorkflowStep {
do<T>(name: string, callback: () => Promise<T>): Promise<T>;
do<T>(name: string, config: StepConfig, callback: () => Promise<T>): Promise<T>;
sleep(name: string, duration: Duration): Promise<void>;
sleepUntil(name: string, timestamp: Date | number): Promise<void>;
waitForEvent<T>(name: string, options: WaitOptions): Promise<T>;
}完整类型定义请参考 api.md。
Steps
步骤操作
Basic Step
基础步骤
typescript
const result = await step.do("step name", async () => {
const response = await fetch("https://api.example.com/data");
return response.json(); // State persisted
});typescript
const result = await step.do("step name", async () => {
const response = await fetch("https://api.example.com/data");
return response.json(); // State persisted
});Step with Config
带配置的步骤
typescript
const data = await step.do(
"call external API",
{
retries: {
limit: 10,
delay: "30 seconds",
backoff: "exponential",
},
timeout: "5 minutes",
},
async () => {
return await externalApiCall();
}
);typescript
const data = await step.do(
"call external API",
{
retries: {
limit: 10,
delay: "30 seconds",
backoff: "exponential",
},
timeout: "5 minutes",
},
async () => {
return await externalApiCall();
}
);Default Step Config
默认步骤配置
typescript
const defaultConfig = {
retries: {
limit: 5,
delay: 10000, // 10 seconds
backoff: "exponential",
},
timeout: "10 minutes",
};| Option | Type | Default | Description |
|---|---|---|---|
| number | 5 | Max attempts (use |
| string/number | 10000 | Delay between retries |
| string | exponential | |
| string/number | 10 min | Per-attempt timeout |
typescript
const defaultConfig = {
retries: {
limit: 5,
delay: 10000, // 10 seconds
backoff: "exponential",
},
timeout: "10 minutes",
};| 选项 | 类型 | 默认值 | 描述说明 |
|---|---|---|---|
| number | 5 | 最大重试次数(使用 |
| string/number | 10000 | 重试间隔时间 |
| string | exponential | 重试策略: |
| string/number | 10 min | 单次尝试的超时时间 |
Sleep & Scheduling
休眠与调度
Relative Sleep
相对时间休眠
typescript
await step.sleep("wait before retry", "1 hour");
await step.sleep("short pause", 5000); // 5 seconds (ms)Duration units: , , , , , , .
secondminutehourdayweekmonthyeartypescript
await step.sleep("wait before retry", "1 hour");
await step.sleep("short pause", 5000); // 5 seconds (ms)时间单位:、、、、、、。
secondminutehourdayweekmonthyearSleep Until Date
指定时间点休眠
typescript
const targetDate = new Date("2024-12-31T00:00:00Z");
await step.sleepUntil("wait until new year", targetDate);
// Or with timestamp
await step.sleepUntil("wait until launch", Date.parse("24 Oct 2024 13:00:00 UTC"));Maximum sleep: 365 days.
Note: and do NOT count towards the 1024 steps limit.
step.sleepstep.sleepUntiltypescript
const targetDate = new Date("2024-12-31T00:00:00Z");
await step.sleepUntil("wait until new year", targetDate);
// 或使用时间戳
await step.sleepUntil("wait until launch", Date.parse("24 Oct 2024 13:00:00 UTC"));最大休眠时长:365天。
注意: 和 不计入1024步的限制。
step.sleepstep.sleepUntilWait for Events
等待事件
Wait in Workflow
工作流内等待事件
typescript
const approval = await step.waitForEvent<{ approved: boolean }>("wait for approval", {
type: "user_approval",
timeout: "7 days",
});
if (approval.approved) {
await step.do("proceed", async () => {
/* ... */
});
}Default timeout: 24 hours.
Timeout behavior: Throws error and fails instance. Use try-catch to continue:
typescript
try {
const event = await step.waitForEvent("optional event", { type: "update", timeout: "1 hour" });
} catch (e) {
// Continue without event
}typescript
const approval = await step.waitForEvent<{ approved: boolean }>("wait for approval", {
type: "user_approval",
timeout: "7 days",
});
if (approval.approved) {
await step.do("proceed", async () => {
/* ... */
});
}默认超时时间:24小时。
超时行为:触发错误并终止实例。可使用try-catch继续执行:
typescript
try {
const event = await step.waitForEvent("optional event", { type: "update", timeout: "1 hour" });
} catch (e) {
// 无事件时继续执行
}Send Event from Worker
从Worker发送事件
typescript
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { instanceId, approved } = await request.json();
const instance = await env.MY_WORKFLOW.get(instanceId);
await instance.sendEvent({
type: "user_approval", // Must match waitForEvent type
payload: { approved },
});
return new Response("Event sent");
},
};Event buffering: Events can be sent before Workflow reaches . They are buffered and delivered when the matching step executes.
waitForEventSee events.md for REST API.
typescript
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { instanceId, approved } = await request.json();
const instance = await env.MY_WORKFLOW.get(instanceId);
await instance.sendEvent({
type: "user_approval", // 必须与waitForEvent的type匹配
payload: { approved },
});
return new Response("Event sent");
},
};事件缓冲:可以在工作流到达步骤之前发送事件,事件会被缓冲,直到匹配的步骤执行时再交付。
waitForEventREST API详情请参考 events.md。
Error Handling
错误处理
NonRetryableError
NonRetryableError
typescript
import { NonRetryableError } from "cloudflare:workflows";
await step.do("validate input", async () => {
if (!event.payload.data) {
throw new NonRetryableError("Missing required data");
}
return event.payload.data;
});typescript
import { NonRetryableError } from "cloudflare:workflows";
await step.do("validate input", async () => {
if (!event.payload.data) {
throw new NonRetryableError("Missing required data");
}
return event.payload.data;
});Catch and Continue
捕获异常并继续执行
typescript
try {
await step.do("risky operation", async () => {
await riskyApiCall();
});
} catch (error) {
await step.do("handle failure", async () => {
await sendAlertEmail(error.message);
});
}typescript
try {
await step.do("risky operation", async () => {
await riskyApiCall();
});
} catch (error) {
await step.do("handle failure", async () => {
await sendAlertEmail(error.message);
});
}Workflow States
工作流状态
| Status | Description |
|---|---|
| Waiting to start |
| Actively executing |
| Manually paused |
| Sleeping or waiting for event |
| Pause requested, waiting to take effect |
| Successfully finished |
| Failed (uncaught exception or retry limit) |
| Manually terminated |
| 状态 | 描述说明 |
|---|---|
| 等待启动 |
| 正在执行 |
| 手动暂停 |
| 休眠或等待事件 |
| 已请求暂停,等待生效 |
| 执行成功完成 |
| 执行失败(未捕获异常或达到重试上限) |
| 手动终止 |
Workflow Bindings
工作流绑定
Create Instance
创建实例
typescript
const instance = await env.MY_WORKFLOW.create({
id: "order-12345", // Optional custom ID (max 100 chars)
params: { orderId: 12345 },
});
console.log(instance.id);typescript
const instance = await env.MY_WORKFLOW.create({
id: "order-12345", // 可选自定义ID(最多100字符)
params: { orderId: 12345 },
});
console.log(instance.id);Create Batch
批量创建实例
typescript
const instances = await env.MY_WORKFLOW.createBatch([{ params: { userId: "1" } }, { params: { userId: "2" } }, { params: { userId: "3" } }]);
// Up to 100 instances per batchtypescript
const instances = await env.MY_WORKFLOW.createBatch([{ params: { userId: "1" } }, { params: { userId: "2" } }, { params: { userId: "3" } }]);
// 每批最多创建100个实例Get Instance
获取实例
typescript
const instance = await env.MY_WORKFLOW.get("order-12345");typescript
const instance = await env.MY_WORKFLOW.get("order-12345");Instance Methods
实例方法
typescript
await instance.pause(); // Pause execution
await instance.resume(); // Resume paused
await instance.terminate(); // Stop permanently
await instance.restart(); // Restart from beginning
const status = await instance.status();
console.log(status.status); // "running", "complete", etc.
console.log(status.output); // Return value from run()
console.log(status.error); // { name, message } if errored
await instance.sendEvent({
type: "approval",
payload: { approved: true },
});typescript
await instance.pause(); // 暂停执行
await instance.resume(); // 恢复暂停的实例
await instance.terminate(); // 永久终止实例
await instance.restart(); // 从开头重启实例
const status = await instance.status();
console.log(status.status); // "running", "complete", 等
console.log(status.output); // run()方法的返回值
console.log(status.error); // 执行失败时的错误信息 { name, message }
await instance.sendEvent({
type: "approval",
payload: { approved: true },
});Rules of Workflows
工作流使用规则
✅ DO
✅ 推荐做法
- Make steps granular and self-contained
- Return state from steps (only way to persist)
- Name steps deterministically
- all step calls
await - Keep step return values under 1 MiB
- Use idempotent operations in steps
- Base conditions on or step returns
event.payload
- 步骤拆分粒度适中且独立
- 通过步骤返回值传递状态(唯一持久化方式)
- 步骤名称具有确定性
- 所有步骤调用都使用
await - 步骤返回值大小控制在1 MiB以内
- 步骤内使用幂等操作
- 基于或步骤返回值判断分支
event.payload
❌ DON'T
❌ 禁止做法
- Store state outside steps (lost on restart)
- Mutate (changes not persisted)
event.payload - Use non-deterministic step names (,
Date.now())Math.random() - Skip on step calls
await - Put entire logic in one step
- Call multiple unrelated services in one step
- Do heavy CPU work in single step
- 在步骤外部存储状态(重启后会丢失)
- 修改(修改不会被持久化)
event.payload - 使用非确定性的步骤名称(如、
Date.now())Math.random() - 步骤调用不使用
await - 将所有逻辑放在单个步骤中
- 单个步骤内调用多个无关服务
- 单个步骤内执行大量CPU密集型工作
Step State Persistence
步骤状态持久化示例
typescript
// ✅ Good: Return state from step
const userData = await step.do("fetch user", async () => {
return await fetchUser(userId);
});
// ❌ Bad: State stored outside step (lost on restart)
let userData;
await step.do("fetch user", async () => {
userData = await fetchUser(userId); // Will be lost!
});typescript
// ✅ 正确:从步骤返回状态
const userData = await step.do("fetch user", async () => {
return await fetchUser(userId);
});
// ❌ 错误:状态存储在步骤外部(重启后丢失)
let userData;
await step.do("fetch user", async () => {
userData = await fetchUser(userId); // 会丢失!
});Wrangler Commands
Wrangler 命令
bash
undefinedbash
undefinedList instances
列出实例
wrangler workflows instances list my-workflow
wrangler workflows instances list my-workflow
Describe instance
查看实例详情
wrangler workflows instances describe my-workflow --id <instance-id>
wrangler workflows instances describe my-workflow --id <instance-id>
Terminate instance
终止实例
wrangler workflows instances terminate my-workflow --id <instance-id>
wrangler workflows instances terminate my-workflow --id <instance-id>
Trigger new instance
触发新实例
wrangler workflows trigger my-workflow --params '{"key": "value"}'
wrangler workflows trigger my-workflow --params '{"key": "value"}'
Delete Workflow
删除工作流
wrangler workflows delete my-workflow
---wrangler workflows delete my-workflow
---Limits
限制条件
| Feature | Free | Paid |
|---|---|---|
| CPU time per step | 10 ms | 30 sec (max 5 min) |
| Wall clock per step | Unlimited | Unlimited |
| State per step | 1 MiB | 1 MiB |
| Event payload | 1 MiB | 1 MiB |
| Total state per instance | 100 MB | 1 GB |
| Max sleep duration | 365 days | 365 days |
| Max steps per Workflow | 1024 | 1024 |
| Concurrent instances | 25 | 10,000 |
| Instance creation rate | 100/sec | 100/sec |
| Queued instances | 100,000 | 1,000,000 |
| Subrequests per instance | 50/req | 1000/req |
| Instance ID length | 100 chars | 100 chars |
| Retention (completed) | 3 days | 30 days |
Note: Instances in state (sleeping, waiting for event) do NOT count against concurrency limits.
waiting| 功能项 | 免费版 | 付费版 |
|---|---|---|
| 单步骤CPU时间 | 10 ms | 30秒(最大5分钟) |
| 单步骤实际运行时间 | 无限制 | 无限制 |
| 单步骤状态大小 | 1 MiB | 1 MiB |
| 事件负载大小 | 1 MiB | 1 MiB |
| 单实例总状态大小 | 100 MB | 1 GB |
| 最大休眠时长 | 365天 | 365天 |
| 单工作流最大步骤数 | 1024 | 1024 |
| 并发实例数 | 25 | 10,000 |
| 实例创建速率 | 100/秒 | 100/秒 |
| 排队实例数 | 100,000 | 1,000,000 |
| 单实例子请求数 | 50/请求 | 1000/req |
| 实例ID长度 | 100字符 | 100 chars |
| 已完成实例保留时长 | 3天 | 30天 |
注意:处于状态的实例(休眠或等待事件)不计入并发限制。
waitingIncrease CPU Limit
提升CPU限制
jsonc
{
"limits": {
"cpu_ms": 300000 // 5 minutes
}
}jsonc
{
"limits": {
"cpu_ms": 300000 // 5分钟
}
}Pricing
定价
Based on Workers Standard pricing:
| Metric | Free | Paid |
|---|---|---|
| Requests | 100K/day (shared) | 10M/mo included, +$0.30/M |
| CPU time | 10 ms/invocation | 30M ms/mo included, +$0.02/M ms |
| Storage | 1 GB | 1 GB included, +$0.20/GB-mo |
Storage notes:
- Calculated across all instances (running, sleeping, completed)
- Deleting instances frees storage (updates within minutes)
- Free plan: instance errors if storage limit reached
See pricing.md for details.
基于 Workers 标准版定价:
| 指标 | 免费版 | 付费版 |
|---|---|---|
| 请求量 | 每日10万次(共享额度) | 每月1000万次免费额度,超出后$0.30/百万次 |
| CPU时间 | 每次调用10 ms | 每月3000万ms免费额度,超出后$0.02/百万ms |
| 存储 | 1 GB | 1 GB免费额度,超出后$0.20/GB-月 |
存储说明:
- 计算所有实例的总存储量(运行中、休眠中、已完成)
- 删除实例会释放存储空间(数分钟内更新)
- 免费版:实例存储超出限制时会执行失败
详情请参考 pricing.md。
Prohibitions
禁止行为
- ❌ Do not mutate (changes not persisted)
event.payload - ❌ Do not store state outside steps
- ❌ Do not use non-deterministic step names
- ❌ Do not exceed 1 MiB per step return
- ❌ Do not skip on step calls
await - ❌ Do not rely on in-memory state between steps
- ❌ 不要修改(修改不会被持久化)
event.payload - ❌ 不要在步骤外部存储状态
- ❌ 不要使用非确定性的步骤名称
- ❌ 不要让单步骤返回值超过1 MiB
- ❌ 不要省略步骤调用的
await - ❌ 不要依赖步骤间的内存状态
References
参考文档
- api.md — Full API reference
- events.md — Event handling and REST API
- patterns.md — Saga, approval, reminders
- pricing.md — Billing details
- api.md — 完整API参考
- events.md — 事件处理与REST API
- patterns.md — 分布式事务、审批流程、提醒机制等模式
- pricing.md — 计费详情
Cross-References (Skills)
关联技能
- — Worker development
cloudflare-workers - — Message queue integration
cloudflare-queues - — Large state storage
cloudflare-r2 - — Key-value references
cloudflare-kv
- — Worker开发
cloudflare-workers - — 消息队列集成
cloudflare-queues - — 大文件状态存储
cloudflare-r2 - — 键值对存储引用
cloudflare-kv