Cloudflare Workflows 按通道迁移:Dynamic Workflows 与 V2 的取舍

Cloudflare Workflows 是否该按内容通道拆成 Dynamic Workflows?本文结合 6 条 AI 发布流程,拆解 Workflows V2 的并发与队列上限、确定性重放和实际迁移成本,并说明为何 publish-{brief_id} 幂等键必须留在 HTTP 调度边界。

发布于

Cloudflare Workflows 按通道迁移:Dynamic Workflows 与 V2 的取舍

每天都有 6 个 Anthropic 侧的发布例程向我的系统发起请求,每一个都会 POST 到同一个静态 PublishWorkflow,实例键为 publish-{brief_id}。5 月 1 日,Cloudflare 发布了 @cloudflare/dynamic-workflows;几天后,又推出了 Workflows V2,其控制平面专门针对 Agent 触发的负载进行了重构。真正值得关注的不是新品发布本身,而是另一件事:我当初为了保证幂等性而选择单一静态工作流,如今不再是沿用平台限制,而成了一个必须重新论证的架构决定。

Cloudflare Workflows 真正让我意外的变化

我原以为这次发布只会宣布“Workflows 可以承载更大规模了”:上限提高、队列加深,再来一次常见的年度升级。但这其实只是公告中较次要的一半。

更重要的变化是,工作流代码如今可以在运行时按租户而不同。@cloudflare/dynamic-workflows 于 5 月 1 日发布,采用 MIT 许可证,并基于 Dynamic Workers 构建。它允许开发者注册一个 WorkflowEntrypoint,在创建实例时再从 Dynamic Worker 解析其执行体。这样一来,步骤图便能随租户变化,不必固化在部署包中。Cloudflare 自己将其概括为“跟随租户的持久执行”。如果你曾尝试用功能开关把客户专属逻辑塞进同一套工作流,就会知道这句话有多准确。

我的 6 个发布例程——news、dev、build、design、marketing、founders、business——本质上就是共享同一个 PublishWorkflow 的 6 个租户。它们不是客户,而是 Anthropic 侧的 AI 例程,每个例程负责一条不同的内容通道。但多租户模型恰好适用:编排主干相同,各通道的具体形态略有差异,最终都调度到同一个 Cloudflare 账户。

几天后 Workflows V2 上线,而那篇公告的叙事重点比数字更值得留意。V2 的架构明确围绕一个前提重做:工作流实例由 Agent 以机器速度 创建,而不是由人点击按钮触发。这正是我的触发模式。发布例程决定上线一篇文章,本质上是一个非人工事件,由此创建一个持久执行实例;V1 的控制平面面向的则是另一种负载形态。

非技术创始人真正需要关注什么

“持久执行”这个词听起来很容易让人望而却步。说白了,它就是一项能熬过系统崩溃的多步骤任务:恢复后从上一个已完成步骤继续,而不是从头重跑。如果 8 个步骤中的第 5 步因为某个 API 宕机而失败,系统只会重试第 5 步,不会重新执行第 1 到第 4 步,也不会让你为这些步骤再付一次钱。

这才是创始人需要在意的部分。按步骤划分的重试边界,同时也是按步骤划分的成本边界。假设流水线在第 3 步和第 6 步分别调用付费 AI 模型,而第 7 步崩溃,你希望重试的是第 7 步,而不是整项任务。对一条付费流水线做非幂等重跑,造成的可不只是数据库里多出一行,而是账单被重复计算。

关于该构建还是暂缓,你可以用一句话告诉承包商:只有当各产品线的逻辑确实出现分化时,才拆分工作流;不能只因为平台现在支持拆分就这样做。 Cloudflare 刚推出了一项强大的新抽象,看到这类能力,人很容易围绕它重新设计系统。但 N 个工作流定义意味着 N 倍的维护工作,只有各通道确实在执行不同任务时,收益才会出现。如果有人说“既然现在能拆,就该把每条产品线都改成独立工作流”,创始人应该追问的是业务流程发生了什么变化,而不是平台增加了什么能力。

我实际运行的架构

这套系统的真实结构很小,完全可以装进脑子里。Anthropic 侧的每个发布例程完成调研并起草 brief 后,都会向网站的 /api/admin/publish 发起 POST。该端点校验 payload、生成实例 ID,然后在名为 PublishWorkflow 的单一 WorkflowEntrypoint 上调用 instances.create。

工作流本身由 8 个具备幂等性的 step.do 阶段组成:

  1. validate(校验 brief schema、slug 唯一性)
  2. ground(抓取引用、解析链接)
  3. generate(调用 Claude 生成正文)
  4. clean(校验 markdown directive)
  5. persist(写入 Postgres、执行版本管理)
  6. index(生成 embeddings、刷新搜索)
  7. cover(生成图片并上传至 R2)
  8. publish(切换状态、ping sitemap)
TypeScript
export class PublishWorkflow extends WorkflowEntrypoint<Env, PublishParams> {
  async run(event: WorkflowEvent<PublishParams>, step: WorkflowStep) {
    const brief = await step.do("validate", () => validateBrief(event.payload));
    const grounded = await step.do("ground", () => groundCitations(brief));
    const draft = await step.do("generate", () => generateBody(grounded));
    const cleaned = await step.do("clean", () => validateDirectives(draft));
    const row = await step.do("persist", () => persistArticle(cleaned));
    await step.do("index", () => reindex(row.id));
    await step.do("cover", () => generateCover(row.id));
    await step.do("publish", () => flipStatus(row.id));
  }
}

调度边界的代码如下:

TypeScript
const id = `publish-${brief.brief_id}`;
try {
  await env.PUBLISH.create({ id, params: brief });
} catch (e) {
  if (isDuplicateIdError(e)) return new Response("already queued", { status: 200 });
  throw e;
}

instances.create 遇到重复 ID 时会抛出异常。这一行承担着关键职责:它是阻止 Anthropic 例程重复触发后再次发布同一篇文章、并让我为其中的 AI 调用支付双份费用的唯一屏障。

为什么 6 条通道只用一个定义?因为所有通道的 8 个阶段完全相同,区别仅在编辑配置包,包括语气规范、受众规范、反模式清单和 brief 提示。这些内容作为运行时数据放在调度 envelope 中传递,而不是写进代码。通道名决定把哪套配置交给第 3 步(generate);其他步骤都不关心通道。

真正的压力点——也是唯一值得认真讨论 Dynamic Workflows 的理由——在于其中一条通道开始需要不同的 步骤图,而不只是不同的配置包。重调研通道希望在生成前多做一轮事实依据补充,并可能在生成后增加事实核查步骤。这是结构差异,不是数据差异。现在它被写成 ground 内部的条件分支,确实能运行;但如果再让 3 条通道加入各自的特殊分支,这类代码很快就会腐化。

迁移到 Cloudflare Dynamic Workflows 的真实成本

这正是 createDynamicWorkflowEntrypoint 带来的能力。系统会在运行时从 Dynamic Worker 加载各通道的工作流代码,因此当天没有触发的通道几乎不产生保留成本。你不再需要承担“所有通道始终打进同一个部署包”的维护负担,也可以独立演进各通道代码,无需重新部署共享主干。

架构图:/publish HTTP 边界持有 publish-{brief_id} 幂等键,作为分流至各通道工作流之前的闸门
幂等键属于调度边界,绝不能放进通道代码。

公告没有着重展开的,是这项能力的真实代价。你原本拥有一个经过类型检查的 WorkflowEntrypoint,步骤输入契约一旦漂移,编译器就会提醒;迁移后则变成 N 个运行时加载的定义,编译器无法提供同样的保障。跨通道步骤契约漂移会从构建期错误变成运行时故障。假如你有 6 条通道,其中 2 条的 persist 步骤因为有人只重构了一半通道、忘了其余部分,而开始期待略有不同的数据行结构,那么问题不会在 CI 运行时暴露,而要等到真实文章尝试发布时才出现。

这次迁移不必全有或全无。把它说成二选一,往往就是过度设计的起点。我的计划是:

  1. 将共享的 8 阶段主干继续保留为静态 WorkflowEntrypoint。这是热路径,6 条通道中有 5 条会原样使用。
  2. 把重调研通道构建成拥有独立步骤图的 Dynamic Workflow,加入额外的依据补充与事实核查步骤。
  3. 在 /publish 边界按通道调度,只需根据 brief.lane 做一行 switch,选择在哪个 binding 上调用 create。

我的判断规则带有一个明确数字:只有当某条通道的步骤图与主干相差超过一个阶段时,才将它迁移到独立的 Dynamic Workflow。 低于这个阈值,在现有步骤中增加条件分支,比维护第二个工作流定义更省成本。超过阈值后,步骤内分支会开始掩盖通道究竟在做什么,独立定义才值得。

一条通道超过阈值,5 条仍低于阈值。两句话就能讲完这份迁移计划。如果承包商拿着同一份 brief,建议我第一天就把全部 6 条通道拆成 Dynamic Workflows,我不会批准。构建成本真实存在,而收益恰好只集中在一条通道上。

Cloudflare Workflows V2 为机器速度触发带来了什么

V2 最醒目的数字是:每个工作流可同时运行 50,000 个实例、排队 2,000,000 个实例;V1 的排队上限是 1,000,000 个。这些数字并非虚荣指标,但也远远超出我的实际规模。6 个例程每天各触发一两次,我的负载大约比新上限低 9 个数量级。

对我的技术栈而言,重要的不是这些数字,而是 V2 的控制平面把 Agent 触发的实例创建设为首要场景。V1 针对的是人工触发模式:用户点击按钮、实例启动,系统处理有突发但仍有边界的负载。V2 假设触发者是进程而非人,速率取决于上游 Agent 的吞吐量,而不是用户界面的点击次数。

确定性重放是 V2 最值得用通俗语言再讲一次的特性。每个步骤都彼此隔离、可以重放、具备幂等性;发生重试时,工作流会从最后一个成功步骤继续。这 恰好 就是我在调度边界用 publish-{brief_id} 实例 ID 手动守住的属性。V1 已经提供按步骤重试的保证;V2 进一步强化了重放语义,让我一直保护的结构性约束也得到下层平台的保障。

本周最实际的动作是:热路径什么也不改。V2 需要通过重新部署来选择启用,而对一条运行良好的幂等流水线来说,最糟糕的做法就是为了追逐已有的语义,匆忙迁移到新的控制平面。我会在把重调研通道构建为 Dynamic Workflow 时将它迁至 V2,因为让新代码直接采用新模型成本很低。其余 5 条静态通道保持原样,直到我有一个不是“平台发布了新版本”的真正改动理由。

我绝不会放弃的那条约束

以 publish-{brief_id} 作为实例 ID 承担着系统稳定性的重任。一旦去掉它,Anthropic 例程在自身一侧重试时,流水线就会再次触发,不仅重复发布同一篇文章,还会让工作流内部每个付费 API 调用都计费两次。

Dynamic Workflows 本身不会直接破坏这条约束,instances.create 的 ID 契约没有改变。真正可能威胁它的,是草率的按通道重构:如果通道代码开始在本地重新派生 ID,例如某条通道为了所谓的“更安全”而把时间戳放进 ID,那么每次重试都会生成唯一 ID,去重机制也就悄无声息地失效了。

无论版本如何升级,下面这条规则都必须保留。在允许任何其他人改动代码前,我甚至愿意把它写在墙上:

这类约束不会出现在发布公告或迁移指南里,因为只有真正经历过它所防止的故障,你才会意识到它的存在。与之对应的成本卡点——即使去重失效,也不能让一次工作流运行演变成失控账单——属于另一层,应设在模型调用层,而不是实例层。两层防护存在的理由相同:当流水线的每一步都在花钱时,结构正确性就是最便宜的保险。

如果在 2026 年 5 月从零开始,我会怎么做

如果今天才开始搭建这套系统,而不是接手一年前的架构决定,我会改变 3 件事。

第一,我会从共享静态主干开始,再为任何真正出现分化的通道增加 一个 Dynamic Workflow,而不是直接创建 6 个独立定义。新抽象出现时,人总想把它用到所有地方,但 N 个工作流定义带来的维护成本,会比规模收益更早到来。6 个定义意味着修复一个 bug 要改 6 个地方,升级依赖要处理 6 个地方,步骤契约也可能在 6 个地方发生漂移。“一条主干加一个例外”才是满足需求的最小拆分方案。

第二,我会从第一天起就把幂等键放在 HTTP 边界。等到发生重复发布事故后再补上 publish-{brief_id},代价要高得多:你必须核对重复发布的数据行、退还受影响的费用,还要在系统已经上线后给调度层补监控。相反,在流水线首次上线前加入 try { create({id}) } catch (dup) {} 模式只需十分钟,却能消灭一整类故障。

第三,我会把 Workflows V2 的确定性视为设计的 最低标准,而不是以后再选择启用的功能。即使永远不会碰到 50k 并发上限,也要让每个步骤都能安全重放。安全重放不是扩展性属性,而是正确性属性。不能安全重放的步骤一定会在重试时出错,而任何规模的系统都会发生重试。

最后这一点,是披着技术决策外衣的资深工程判断。陷阱在于把平台新能力当作等待采用的功能,真正的工程纪律则是把它们当作设计约束——无论你最终是否会用到那些容量余量。

所有租户运行相同逻辑时,还需要 Dynamic Workflows 吗?

不需要。如果步骤图完全相同、只有数据不同,就把数据放进调度 payload,继续使用一个静态工作流。只有代码本身因租户而异,也就是步骤图不同而不只是参数变化时,Dynamic Workflows 才能体现价值。

Workflows V2 会破坏现有的 V1 工作流吗?

V2 是经过重构的控制平面,重点支持确定性的 Agent 触发执行。应把迁移视为需要主动选择的操作;移动热路径之前先验证幂等性,也不要仅仅因为新版本出现,就迁移运行正常的代码。

现在实际的并发上限是多少?

每个工作流可同时运行 50,000 个实例、排队 2,000,000 个实例,原来的排队上限是 1,000,000 个。对大多数运营者来说,这远超实际需求;相比新上限,V2 更重要的特性是确定性重放。

@cloudflare/dynamic-workflows 已可用于生产环境,还是仍处于预览阶段?

它于 2026 年 5 月 1 日发布,采用 MIT 许可证,并基于 Dynamic Workers 构建。真正应该作为门槛风险来评估的是库的成熟度和你的幂等契约,而不是许可证。如果调度层足够可靠,那么这套库的就绪速度会快于你的迁移计划。

创始人应该在什么时候花钱请工程师做这次迁移?

当某条产品线的自动化逻辑确实与其他产品线出现分化时——步骤图不同,而不只是参数不同。仅仅为扩展规模而拆分还为时过早;逻辑分化才是真正的触发条件。如果你的团队也需要算清这类迁移账,这正是我通过 DVNC.dev 提供的架构评审服务。

发布日期
分类
Build
Airtable 替代品怎么选?NocoDB、Baserow 等工具的价格与适用场景

Airtable 替代品怎么选?NocoDB、Baserow 等工具的价格与适用场景

想换掉 Airtable,先分清是席位太贵、容量不够,还是缺少客户门户。本文对比 NocoDB、Baserow、SeaTable、Grist、Smartsheet、Notion 和 Softr,拆解价格、免费额度、自托管、API、自动化与权限差异,帮你按真实工作流选型,并在迁移前验证关联数据、集成和恢复方案。2026年11月10日Build
2026 年 proxy 代理服务推荐:Bright Data、Oxylabs、Decodo 等 7 家怎么选

2026 年 proxy 代理服务推荐:Bright Data、Oxylabs、Decodo 等 7 家怎么选

proxy 代理服务该怎么选?对比 Bright Data、Oxylabs、Decodo、Webshare、ThorData、IPRoyal 与 NetNut,梳理住宅、数据中心、ISP 和移动代理的价格、试用、KYC 与会话控制,分清原始网络、托管解封和抓取 API 的职责,按有效记录成本和实际任务需求筛选。2026年11月10日Build
NVIDIA OpenShell:为 AI 智能体划定可执行的权限边界

NVIDIA OpenShell:为 AI 智能体划定可执行的权限边界

NVIDIA OpenShell 如何限制编程智能体的文件、网络和凭据访问?本文梳理受支持的平台、CLI 安装与 OpenCode 启动流程,解释哪些策略可实时更新、哪些变更需要重建沙箱,并给出可审查的编程策略模板、权限测试方法和团队落地场景,帮助平台团队在开放真实项目与服务前看清实际授予的权限。2026年11月9日Build
CodeRabbit 价格详解:席位费用、用量限制与附加收费

CodeRabbit 价格详解:席位费用、用量限制与附加收费

CodeRabbit 价格怎么算?本文梳理 Essentials、Team、Advanced 与 Enterprise 的席位收费、年付折扣、PR 审查额度及关联仓库限制,并列出不同团队规模的预算算例。了解免费版和开源方案的适用范围,分清超限文件审查、Agent 分钟数与安全扫描费用,再按实际工作流和安全需求选择套餐。2026年11月9日Build
2026 企业杀毒软件怎么选:六款小企业方案、价格与响应服务对比

2026 企业杀毒软件怎么选:六款小企业方案、价格与响应服务对比

企业杀毒软件怎么选,关键在于谁来管理设备、谁来处理告警。本文对比 Bitdefender、Microsoft Defender、ESET、Sophos、CrowdStrike 与 Malwarebytes,梳理美元价格、设备额度、服务器授权和托管响应范围,帮助小企业按现有订阅、设备类型与管理能力确定候选方案。2026年11月8日Build
Paperclip AI 评测:多智能体协作怎么管,部署前要看什么

Paperclip AI 评测:多智能体协作怎么管,部署前要看什么

Paperclip AI 能把分散的 AI 智能体组织成可追踪的工作流,但安装管理面板并不等于完成权限与验收配置。本文梳理官方安装方式、运行时与模型支持、任务交接、预算策略和审批边界,并对比 OpenClaw 与 Hermes Agent,帮你判断是否值得花一个周末试用,以及上线前应检查什么。2026年11月7日Build
Supabase 是什么?看懂 AI 应用背后的数据库、权限与后端

Supabase 是什么?看懂 AI 应用背后的数据库、权限与后端

Supabase 是什么,为什么 AI 应用构建工具常用它做后端?本文从 Postgres 数据库、登录认证、文件存储、实时更新与向量搜索讲起,梳理 Lovable、Bolt、v0 和 MCP 的接入方式,解释 RLS 权限、项目控制权与迁移边界,帮你在接收真实客户数据前,明确需要验证的隔离、恢复和交接事项。2026年11月7日Build
AI IDE 怎么选?2026 年 Cursor、VS Code、Zed 等 6 款编辑器对比

AI IDE 怎么选?2026 年 Cursor、VS Code、Zed 等 6 款编辑器对比

AI IDE 怎么选?比较 Cursor、VS Code 搭配 GitHub Copilot、Windsurf(现为 Devin Desktop)、Zed、Kiro 与 JetBrains AI,梳理价格、免费方案、智能体模式、模型接入、BYOK、本地推理、隐私边界与团队管控,帮你按工作流判断是否值得迁移。2026年11月6日Build
订阅通讯

每周日,一封信。写运转中的系统,不写热评。

每周一期。无垃圾邮件。随时退订。