
Durable Objects 的 Alarm 漏写一行判断,8 天烧掉 34,895 美元,全程没预警
一位开发者公开完整时间线:onStart() 每次唤醒都无条件重排 Alarm,叠加 60 多个预览环境,峰值期每天跑了约 9300 亿次行读取。Workers 用量通知只监控 CPU 时间,DO 读写没有任何告警,也没有硬性花费上限。
原文来源:Hacker News — 一位开发者公开自己被 Durable Objects 烧掉 34,895 美元的完整时间线、根因和修复代码,以及平台为什么一句提醒都没发。
一位开发者在 Hacker News 上贴出了自己的账单事故,原文标题很直白:Durable Object 的 Alarm 循环,8 天 34,000 美元,零用户,平台没有任何预警。
文中提到的 Alarm 指的是 Durable Objects 的定时唤醒接口,也就是代码里的 setAlarm 和 getAlarm——不要和 Cloudflare 的 Cron Triggers 混为一谈。
事故时间线
- 4 月 3 日:循环开始(此前这个项目的 DO 用量为零)
- 4 月 4 日到 5 日:峰值达到每天约 9300 亿次行读取
- 4 月 11 日:发现问题并修复
- 4 月 15 日:收到 34,895 美元账单,此时还没有收到计费方的任何回应
整个循环跑了 8 天,期间这个项目一个真实用户都没有。截至发帖,这笔账单仍在申诉中;作者也提到,作为一个产品还没上线的个体开发者,这笔钱是他的全部积蓄。
—— 广告 ——
根因:一行缺少判断的代码
问题出在 DO 实例的 onStart() 处理函数里。每次实例被唤醒,它都无条件调用 setAlarm 重排下一次 Alarm,而不检查是否已经有一个 Alarm 在排队:
// 危险写法
async onStart() {
await this.ctx.storage.setAlarm(Date.now() + 60_000)
}单看这一行没什么问题。真正放大它的是另一个因素:这位开发者开了 60 多个预览环境,每个部署都会创建独立的 DO 实例。这些实例各自唤醒自己、各自重排 Alarm,最后叠成一个自我健康检查的死循环。
修复方式就是加一次读取判断:
// 安全写法
async onStart() {
const existing = await this.ctx.storage.getAlarm()
if (!existing) {
await this.ctx.storage.setAlarm(Date.now() + 60_000)
}
}作者还列了几条同样值得做的事:预览环境里干脆去掉 DO 绑定;部署一个预算监控的 kill switch Worker;在安排 Alarm 之前加一个检查当前 Alarm 状态的熔断器。
为什么平台没有预警
这是整件事里最值得警惕的部分。
作者的说法是:Cloudflare 的 Workers Usage Notifications 只监控 CPU 时间,不监控 Durable Object 的行读取和行写入。仪表盘和 Wrangler 配置里也没有为 DO 操作提供硬性花费上限。也就是说,行读取从零涨到每天 9300 亿次的过程中,没有任何一个机制会触发告警。他是在账单出现的时候才知道出事了。
为什么这件事值得写进你的部署清单
少写一个判断,是每个开发者都可能犯的错误。真正让错误变成 3.4 万美元的,是三层防护同时缺失:
- 代码层:没有先检查 Alarm 是否已经存在
- 环境层:预览环境照搬了生产环境的绑定,60 多个实例各自跑循环
- 平台层:缺少针对 DO 读写的用量告警,缺少可配置的花费上限
他认为,平台层缺失的那部分,目前获得的关注远远不够。作者还提到一个时间点上的巧合:事发时正值 Cloudflare 的 Agents Week,官方正在密集推广让个人开发者用 Durable Objects 搭 AI 智能体——博客、公告、一整套宣传。用他的话概括,这是在主动把独立开发者拉进一个能静默产生五位数账单的产品,而计费护栏却不到位。
这个批评是否公允,可以讨论。云平台按用量计费、不设硬上限是行业惯例,AWS 和 GCP 也不提供真正意义上的消费天花板(这句是编者的判断,不属于原帖内容)。但基础事实是清楚的:把一个"专门面向个人开发者的用量型产品"和"只监控 CPU 的通知系统"配在一起,风险敞口就是不对称的。付费的一方拿到的信息,比收费的一方少得多。
用量计费的风险,结构上就是不对称的
(下面是编者自己的分析,不是原帖内容。)
把这件事放大看,它暴露的是用量计费模式的一个结构性缺陷。
按用量付费对开发者是好事:业务小的时候成本接近于零,不用提前买容量。但它有一个隐含前提——付费方必须能实时看到用量。这个前提在传统云资源上基本成立:CPU、内存、带宽都有现成的监控图表,超了能收到告警。而像 DO 行读取这类新的计费维度,监控和告警往往滞后于产品发布:计费口径先上线,防护工具后补,中间的时间差全由用户承担。
更麻烦的是,这类维度的单位量级和直觉差得很远。9300 亿次行读取听上去像个天文数字,但它只是"唤醒频率 × 实例数 × 每次读取行数"层层相乘的结果——每个乘数单独看都不起眼,写代码的时候也没人会把这个乘法算一遍。
所以对个人开发者来说,一条可操作的原则是:任何新接入的按量计费资源,先写一行监控再写第一行业务代码。监控不需要多复杂——每天拉一次用量、跟昨天比、涨了 3 倍就发一条通知给自己。这次的账单之所以能滚到 3.4 万美元,核心原因不是 bug 难修,而是从第 1 天到第 8 天,作者完全不知道数字在涨。
还有一条更实际的建议:把云账号的账单告警阈值设低一点。大多数平台都支持"预计月度支出超过 X 时通知",这个功能的默认值通常高得没有意义。花十分钟把它调到"超过 50 美元就提醒",能挡掉的正是这类失控。
落到自己的项目上
对独立开发者来说,这件事可以直接转成几条部署习惯:
- 任何按量计费的资源,都要自己写一个余额或用量监控,不要指望平台通知。通知系统通常只覆盖一部分指标,且默认关闭或默认阈值很高。
- 预览、测试、CI 环境要与生产环境的绑定隔离。一个容易被忽略的点是:预览环境不是免费的,它按同样的单价计费。
- Alarm、轮询、重试这类自我驱动的逻辑,必须能回答"现在有几层循环在跑"。任何无条件重排自身的代码,都要先想清楚它的触发源有几个。
- 给关键资源设一个外部 kill switch。它不一定优雅,但在凌晨三点它能救你。
一场事故的代价是 34,895 美元和八天。把上面的清单抄一遍,成本是半小时。这个性价比,大概是今天读到的最划算的一笔交易。
© 2026 四月
原文链接:https://www.aprilzz.com/indie/cloudflare-durable-objects-34k-bill
相关文章
每月 20 美元的技术栈,撑起多个 10K MRR 的产品
一个独立开发者公开自己的极简技术栈:单台 VPS、Go 单二进制、本地显卡跑 AI、SQLite 扛并发。成本压到极低,也就有了无限跑道。
周末花 10 美元,他建了一个只搜个人网站的搜索引擎
受够了被 SEO 垃圾淹没的搜索结果,作者用一台租来的 GPU 和一个本地小模型,索引了 56 万个网站主页。整个项目成本约 10 美元:怎么爬、怎么让 AI 分类、怎么在睡醒前自动清理垃圾源。
独立开发者的省钱方案:月租不到 10 欧元的全欧盟技术栈
云服务器、邮件、分析、监控、支付、认证、CDN——独立开发者在验证想法阶段,能不能把整条基础设施的月成本压到 10 欧元以内?这篇指南给出了逐项对比和推荐。