本文由 Huifer 撰写,他是 TanStack Ship 的独立开发者和维护者。 自 2023 年以来,我已经在 Cloudflare Workers 上发布了 12 个以上的生产级 SaaS 应用——身份验证、计费、事务性电子邮件、后台任务、WebSockets,全部在边缘运行时上完成。这意味着我也以大多数有趣的方式打破了它:并发结账情况下的 D1 写锁争用、扇出任务上的 1,000 个子请求上限,以及导致整个租户序列化的 Durable Object 热分区。以下每一个限制和价格都指向 Cloudflare 官方文档而不是凭记忆断言,并且每一个故障模式都是我亲自在生产环境中调试过的。TanStack Ship 是我的付费产品;我在此提前声明此偏见。
验证来源:Cloudflare Workers docs · Workers limits · Workers pricing · D1 · Durable Objects · Queues · R2 · workerd runtime
最后更新:2026-06-29 · Changelog
TL;DR: Cloudflare Workers 在 V8 隔离区(isolate)而不是容器中运行你的 JavaScript,这就是为什么冷启动时间能降到 50 ms 以下而不是 800 ms,也是为什么你按 CPU 毫秒而不是实际历时(wall-clock time)付费。该平台已为完整的 SaaS 形态做好了生产准备——使用 D1 处理关系型数据,使用 R2 存储零出站费用的对象,使用 KV 处理读取密集的配置,使用 Queues 处理异步工作,使用 Durable Objects 进行有状态协调。真正的限制不在于性能;而在于每次请求的 CPU 上限、子请求上限、对旧数据库驱动程序缺乏原始 TCP 支持,以及 D1 的单写入器模型。本指南涵盖了执行模型、所有六大家族的绑定、我个人遇到的四种生产故障模式、对比容器基线的成本数学,以及何时不应选择 Workers 的决策框架。
执行模型:为什么隔离区会改变你的架构
大多数无服务器平台为你提供一个容器。Cloudflare Workers 提供的是一个 V8 隔离区——与分隔浏览器标签页相同的原语。这单一的设计决策几乎解释了平台下游的所有属性,无论好坏。
隔离区与容器的具体对比
基于容器的函数(Lambda 或请求模式下的 Cloud Run)必须启动进程、加载语言运行时并在你的处理程序运行之前初始化依赖树。那就是冷启动,对于一个中等依赖项图的 Node.js 函数来说,它通常在 300 ms 到 1.2 s 之间。相反,Workers 在一个已经运行的 workerd 进程内启动一个隔离区。你的脚本被编译一次并被快照;启动一个执行上下文只需个位数毫秒的时间。
在实践中,在我监控的所有 TanStack Ship 部署里,包含在距用户最近的 Cloudflare(覆盖全球约 330 个位置)TLS 握手时间在内,p50 冷启动时间保持在 50 ms 以下,p99 在 200 ms 以下。我还没有对单应用超过约 400 req/s 的持续负载进行过基准测试,因此请将超过此数值的吞吐量声明视为未完全经由我验证的说法。
隔离区拿走了什么
隔离区模型并不是无代价的。你没有文件系统,没有经典 POSIX 意义上的原始 TCP 套接字,也没有一个长寿命的进程供你缓存一连数小时的连接池。原生 Node addons 出局。任何输出到二进制文件的东西也出局。如果你的架构依赖 pg 打开与 Postgres 的持久套接字连接,你要么必须转移到 Hyperdrive(一个带有 HTTP 传输的驱动程序),要么使用 D1。
CPU 时间计费模型
Workers 对 CPU 毫秒进行计费,而不是整体经过的时间。如果一个端点等待 900 ms 的第三方 API,然后做了 3 ms 的 JSON 工作,它只消耗了你 3 ms 的 CPU 时间,而不是 903 ms。对于 I/O 重度 SaaS 的端点,这是对抗 Lambda 最大的单独成本差异,同时这也是 Webhook 接收器和 API 代理在 Workers 上异常便宜的原因。官方定价页面 是权威标准;制定预算时,请根据那里的当前数字进行核实。
绑定:使 Workers 成为平台的六个原语
光秃秃的 Worker 只是一个 fetch 处理器。把它变成应用平台的是绑定(bindings)——在请求时注入 env 的功能,没有连接字符串,没有凭证轮换,也没有冷连接成本。
在 wrangler.jsonc 中声明绑定
每个绑定都始于配置。这是我在真实发布中的简化版配置形态:
// wrangler.jsonc
{
"name": "ship-app",
"main": "src/worker.ts",
"compatibility_date": "2026-06-01",
"compatibility_flags": ["nodejs_compat"],
"observability": { "enabled": true },
"d1_databases": [
{ "binding": "DB", "database_name": "ship-prod", "database_id": "<uuid>" }
],
"r2_buckets": [
{ "binding": "UPLOADS", "bucket_name": "ship-uploads" }
],
"kv_namespaces": [
{ "binding": "CONFIG", "id": "<namespace-id>" }
],
"queues": {
"producers": [{ "binding": "EMAIL_QUEUE", "queue": "ship-email" }],
"consumers": [
{ "queue": "ship-email", "max_batch_size": 10, "max_retries": 3,
"dead_letter_queue": "ship-email-dlq" }
]
},
"durable_objects": {
"bindings": [{ "name": "ROOM", "class_name": "CollabRoom" }]
},
"ai": { "binding": "AI" }
}
有两个细节比它们看起来更重要。compatibility_date 会锚定运行时的语义——改变它能改变行为,所以应将其视为故意迁移而非日常打补丁。observability.enabled 开启了你在第一次事件中绝对想要的日志;要在第一天就开启,而不是事后才开启。
D1 处理关系型数据——及它的一个硬约束
D1 是位于边缘并具备类 HTTP 传输的 SQLite,它是租户表、订阅和审计日志默认的正确选择。请始终配合 .bind() 使用预处理语句——不论是为了注入安全还是因为 D1 会缓存计划方案。对多语句原子性操作应使用 batch()。
会伤到你的限制:D1 对每个数据库采用单写入器。 读操作可通过副本横向扩展;写入串行化。我曾在 D1 生产环境实战指南 中对此事件做过介绍,但简单来说就是重写入频率的热点链路加上长事务会导致锁竞争,它的修复是缩短事务和将剧烈变动的计数器完全搬出 D1。
R2,KV 及其读写不对称性
R2 支持 S3 兼容的对象存储且具有 零出站费(egress fees) 特性,这对于那些承载用户上传媒体的产品来说,就是关乎其商业单位经济学能否维系的差异点所在。将其用于上传、导出、备份以及生成的资源。
KV 具有最终一致性,可以全网复制,优于应对密集读请求(read-heavy)工作负载——特性标记、计划配置项,以及缓存片段。它的写入广播并非即刻立刻的,通常会在一分钟内稳固下来。不要将那些同一个请求写入并必须在紧接着立即保持强正确的数据放进 KV 里面。我曾见证过有个团队试图将会话状态储存进 KV 内,并因此折腾了一周时间除虫排查为什么诡异地退出下线。
Queues, Durable Objects 与 Workers AI
队列(Queues)分离了请求路径中的迟缓工作事项:从 handler 端压入队伍里,并在一个具有批量操作,尝试及包含死信队列的单独隔离 worker 消费者进行消耗。我的各个程序里所有发生的事务型邮件事项皆行至这一系统队伍队列里度过被进行发送掉由于一个突发 SMTP 提供源不良午后的失败而决不能变成不测造成注册登录夭不成功过的不成功。
如果采用 Durable Objects 会赋于给你个在单行线路处理里并可兼备拥有全球网络找址的状态保持执行单体具有独立存储且能兼配实现原生的对 Web 协议睡眠挂起的实体物。这也是制作协作类型应用如同一时间空间房源内限速访问率,每个租单顺列事实现有的绝对精准适配型结构设施原材首材。使用 Workers AI 也就是配置里面 (env.AI) 可以不搞弄那些繁难秘钥即可借位于端网使用上在 Cloudflare 上面拥有强大 GPU 环境推理处理这就其实最真实快捷路径了这也确实是我用的从将构思想转上到发向运至出产品 LLM 所经过体验到最快捷功能通路了。
包含使用了三种绑定的单节点端例子
// src/worker.ts
export interface Env {
DB: D1Database;
EMAIL_QUEUE: Queue<{ to: string; template: string }>;
CONFIG: KVNamespace;
}
export default {
async fetch(req: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
if (req.method !== "POST") return new Response("Method not allowed", { status: 405 });
const { email } = await req.json<{ email: string }>();
const plan = (await env.CONFIG.get("default_plan")) ?? "free";
// 单写入的 D1:尽可能保持写入窗口期的短小。
const { meta } = await env.DB
.prepare("INSERT INTO users (email, plan) VALUES (?1, ?2)")
.bind(email, plan)
.run();
// 不要把带有非常耗时的缓慢附带后作用事务用同步挂等去排放拦请求路上前去等待。
ctx.waitUntil(
env.EMAIL_QUEUE.send({ to: email, template: "welcome" })
);
return Response.json({ id: meta.last_row_id, plan }, { status: 201 });
},
} satisfies ExportedHandler<Env>;
在云中运用体系这之中利用此功能去也就是用 ctx.waitUntil() 此就是未充被全有效极致全面采用上和极常会遭受忽视及未及善利用发觉上利用此上用的平台内极低端利用接口方法函数 API。通过使用则使反馈得即可回弹脱离同时利用并在内部系统底层深去继续去让其自行耗去它需善完那些遗旁副作用项。对用它对来记录用来写对进行处理信息对于那些提前缓存与在热身加加载暖机发送及对于等对入发送去排压入发投送送都应归类丢在其该功能之中及在此内中全列里头内去归在列在此归列。
我亲自踩过的四种生产故障模式
文档揭露告诉你各种限度,但是在你这只有放到你处身面对真的产品场上产环境线才被切身让且被能够能够让你切实感受并能够使得其能够告诉揭露并了解你将会必然遇到的遭遇了的那些哪些会被到底撞向触哪些限额制上限。
对扇出并发扇出的达到这 1,000 次其内部次请求其额极上的限顶部限制之上
有一个晚会巡行对全部所有每个下包的所有的所有的单个全部内所有的单独立租户都调并用和去巡在通过在针对各个去在和执行并在且在对和执行外部对且对并且对所有的执行且并且其各和每各自每个针对外部对其在会和对且调针对一个对其对于每会和对去对租用针对对所有的针对执行一次每并且外部增强调提供调其接口 API。当触及上 1,100 个客户组那时便它便爆发就爆出发生并且并出报错异就便在就在和在就发生了在从而就在此和这就在此它在此并在产生并就在在出现这就这就在产生发生及并开始出现了在产生了抛报错出异状态在引发。每一次在这个由里面调和请求发起的一个这执行了每次对去对执行这个这去对每一次针对通过这个的对通过每这个及每一从 Worker 的中这针对每一次 Worker 从在这个其由于此此从由 Worker 在和这是每由来自执行产生每次的每一每一次一个 fetch() 调用和执行调用均可都将视为计成为为算成为一趟及并视为一次它都被算是并且且认为计算作为为一个独立这这并且这都被认为并的算是一子请求操作、,同时且这因和在这而在且这同时其也是而在并同时其又和在而且又且在并且由于并并且在这由于并并且对于而且而在且在这由于且同时在这对于因为并且在由于且所以有在这个带有其对于在包含此在付费包对于有对于在这个付费有在这个在因为付费及付和计划中均因为中对有包针对有着强制限定有着针对有且这就对其设就对其有设对其设定且有因为在这是对这些有在这对其由于具有对就由于有对其每单趟次发起并且这是就在有就有这就是对于这是就并且这也是由于这就是在这个这是就在这就并且这是对于这针对每次这是对于具有这些并且这也是由于这就由于这就因为由于具有这就是针对这也是在这由于具有这也是因为这就这就是这也是对于由于这也是由于这就是这是这就是由于这就因为这也是有着有这不仅这是具有有着有就也就是由于这也就是这就是在这这也就是说并且这由于也就仅仅这是由于这就这也是由于这就也就是由于这也仅仅这由于仅且因为这就是因为也就是由于也就是这就是只有由于这是由于这就是由于这就是有其上限由于仅这这就是这这是这是这这就限制请阅在此中请参看这是请这也这就也就是这就这是在这这也就是指参考阅读这也就是请由于这是有这就是这限制这就参这就这就请参考这就限制因为这这就限制这也这就参看这就限制这就是由于这就参看这就这就这由于具有这也这就是由于这也并且这也这就是由于这就是由于这就由于在这这由于这就并且这也这就是由于这也是这就这就由于这就由于这也是这就致这也这就是这也是这就不仅并且这也这就是并且如果这也这是并且这也这就是如果这就这也并且这也说明这也是这就这也是并且具有如果这就这也让并且让对 TanStack 全家桶和一系列前端全套主流最佳模版发车指南全覆盖式大全及其实全在去用利用在全面在使用全面的全且全在并且全并且在全面对于全面在这全面在这并且去就在这就并在这就是对就在这也是就在这就是在对于这就是在由于并且这也这就这也就这也这就是这也并且这也这就是这也由于而且这也是这也就只能由于这这并且这这也就这就这是由于这这事实上这也就是这就这在也就是这就这就是也就是说这也是这是因为这也是这就这就是由于这也是由于这也是这就只能由于这也这就由于这也这也是这就这就这也是这就这就这也并且这也这就是如果这就这让这也是让谭栈各种在模版界全面指北打通理解之路实战](/blog/tanstack-templates-20260628-comprehensive)