我们为什么在 Cloudflare Workers 上构建 YouBase
我们构建了 YouBase——一个平台即服务(PaaS),让 AI 编程 Agent 可以部署和管理全栈 Web 应用。不只是调用 API,而是真正地编写代码、发布上线、测试验证、迭代改进、重新部署。可以把它想象成 Vercel 或 Heroku,只不过你的"开发者"是 Claude 或 GPT。
技术挑战从一开始就显而易见:AI Agent 的迭代速度极快。它们部署代码、访问端点、遇到错误、修复代码、再次部署,有时每小时要循环几十次。传统平台并非为这种紧密的反馈循环而设计。我们需要能在几秒内完成的部署、默认的全球分发,以及强大的多租户隔离——因为被部署的代码是不受信任的,而且是即时生成的。
我们也不想从头构建编排系统、复制层或多租户隔离框架。
我们选择了 Cloudflare Workers,并在大约两个月内完成了生产上线。
上线两周后,我们需要更新所有活跃租户 Workers 的验证逻辑。在传统平台上,这需要协调滚动部署、分阶段发布,还会有一批迟迟未更新的实例。而在我们的架构下,只需重新部署一个 Service Bindings Worker。大约三十秒后,每个租户都运行着新的逻辑,没有任何停机,也不需要重新部署任何租户。就在那一刻,这套架构从理论变成了现实。
架构概览

YouBase 采用混合架构。控制面(Go、PostgreSQL、Redis、Lambda 等)负责项目创建、部署、计费和管理。数据面完全运行在 Cloudflare Workers 上。
每个项目都有专属的 Worker,配备独立的 D1 数据库和独立的 R2 存储桶。没有共享数据库,没有共享存储。Bindings 按租户隔离,因此即使某个 Worker 行为异常,也无法访问其他租户的状态。
一个调度器 Worker 使用存储在 KV 中的域名映射,将传入请求路由到正确的租户 Worker。我们还运行了一个共享 Worker,通过 Service Bindings 提供公共逻辑,包括验证、计费规则、框架工具和功能开关。
我们不需要管理区域、副本或节点池。一切都自动运行在 Cloudflare 的 300 多个节点上。
站在 Cloudflare 的肩膀上
Workers for Platforms:无需编排的多租户
我们需要真正的多租户。如果用 Kubernetes,那意味着网络策略、每租户的 Pod、资源配额、密钥管理、每租户的数据库,以及大量的运维开销。
Workers for Platforms 将多租户隔离作为运行时的原生特性提供。每个工作空间都有一个独立的 dispatch namespace,拥有自己的 Workers 和 bindings。调度器从 KV 读取域名映射,并将请求转发到正确的 Worker:
const workerName = getWorkerNameFromHostname(url.hostname);
const dispatcher = getDispatcher(url.hostname, env);
const backendWorker = dispatcher.get(workerName);
return await backendWorker.fetch(request);
每个 Worker 在自己的 V8 隔离环境中运行。租户之间无法访问彼此的 bindings 或内存。没有共享文件系统,也没有共享环境变量。
让我们惊讶的不是隔离本身,而是我们需要配置的基础设施少得出乎意料。我们没有配置集群,没有配置网络,没有选择区域。我们只是创建了 namespace 并部署了 Workers。
这里主要的摩擦点是调试 namespace 路由。调度路径中的故障通常以通用的 fetch 错误形式出现,且堆栈上下文有限。我们最终添加了关联请求头,以便能从调度器追踪到租户 Worker,再到共享 Worker。
即便有这些小问题,对于不受信任的生成代码而言,这种方式仍然比运行 Kubernetes 简单得多。
D1 + Session API:边缘的一致性
边缘数据库通常以一致性换取低延迟,但这种权衡对我们的使用场景来说是不可接受的。
D1 的 Session API 通过书签(bookmark)解决了这个问题。每次写入后,数据库会返回一个书签(事务日志位置)。如果你在下一个请求中发送该书签,D1 保证你能读到自己刚写入的数据:
const BOOKMARK_HEADER = "x-es-sticky-session-db-bookmark";
const bookmark = request.headers.get(BOOKMARK_HEADER) || "first-primary";
const session = env.D1.withSession(bookmark);
response.headers.set(BOOKMARK_HEADER, session.getBookmark());
我们通过请求头传递书签。框架提取书签、创建 D1 会话、执行查询,并返回新的书签。
这让我们在无需协调服务器的情况下,获得了强大的读后写一致性保证。所有写入都发送到主节点以保证一致性,读取则发送到最近的副本以提升速度。如果副本尚未赶上你的书签位置,它会等待。
从运维角度看,这远比管理 PostgreSQL 副本和跨区域调试复制延迟简单得多。
Service Bindings:即时更新的共享逻辑
我们最担心的运维问题,是随着 Workers 数量增长,如何更新共享逻辑。
安全规则、验证、计费、速率限制、功能开关。
传统的答案是对所有租户 Workers 进行滚动升级。
Service Bindings 让我们可以运行一个单一的共享 Worker,租户 Workers 通过原生 RPC 调用它。没有 HTTP 层,没有 token 认证,开销低于一毫秒。
我们使用这个共享 Worker 来处理:
- SQL 验证
- 计费计算
- 速率限制
- 功能开关
- 框架工具
- 核心业务规则
- 其他共享基础设施关注点
当我们更新这个 Worker 时,所有租户立即看到新的行为。
这是消除大部分运维负担的关键。如今,大量租户请求都通过 Service Bindings 流转。
可观测性:Tail Workers 和 Analytics Engine
我们无法要求用户自己埋点日志。AI Agent 生成的代码可能会崩溃、陷入循环或产生异常行为。我们需要"开箱即用"的日志和指标。
Tail Workers 捕获控制台输出、异常、请求元数据和时序信息。我们构建了一个摄取服务,对这些事件进行缓冲,并通过 SSE 将它们实时推送给客户端。用户运行 edgespark log tail 即可看到延迟不超过一秒的实时输出。
Analytics Engine 负责指标层。我们追踪每个项目、每个域名、每个端点的维度。传统系统在这种基数级别下往往会崩溃。
env.ANALYTICS_ENGINE.writeDataPoint({
blobs: [projectId, environment, customDomain, method, status],
doubles: [cpuTimeMs, wallTimeMs],
indexes: [endpoint]
});
写入是非阻塞的,结果可以通过 SQL 查询,且不会有基数爆炸问题。
我们将其用于仪表盘、计费、使用报告和速率限制。
配套基础设施:R2 和 KV
R2 提供兼容 S3 的对象存储。每个项目都有专属的存储桶。预签名 URL、分片上传和流式传输均按预期工作。
KV 存储域名到 Worker 的路由映射。调度器在每个请求时查询 KV,更新在几秒内全球传播。
为什么集成平台很重要
这种集成在实践中意义重大——因为我们没有花好几周时间将 Lambda、RDS、S3 和 API Gateway 连接在一起。我们没有编写连接池逻辑,没有配置 VPC 端点,没有在服务之间设置 IAM 策略,也没有运行自己的时序数据库来收集指标。
Workers 通过 bindings 调用 D1 和 R2。Service Bindings 通过原生 RPC 连接 Workers。KV 处理路由。Tail Workers 捕获日志。Analytics Engine 摄取指标。这些组件配合得天衣无缝。
在实践中,这意味着我们在那两个月里,大部分时间都在构建产品,而非基础设施。
技术经验总结
我们曾对边缘 SQLite 持怀疑态度,但 D1 配合 Session API 证明我们错了。它以比 PostgreSQL 副本更低的运维复杂度,提供了全球一致的数据访问。
多租户变成了一个配置问题,而非架构问题。当运行时通过 V8 隔离环境和 dispatch namespace 支持隔离时,你无需自己构建隔离机制。
Service Bindings 解决了更新共享逻辑的运维难题。一次部署就能更新所有租户的安全规则、工具函数和核心功能。
平台约束实际上改善了我们的设计。没有长时间运行的进程,没有文件系统,用 SQLite 而非 Postgres。这些约束推动我们走向更简单、更可靠的模式。
最难的部分不是 Cloudflare 本身——而是下定决心选择它。 我们花在评估备选方案上的时间,比调试生产问题花的时间还多。
我们还以为可观测性建设需要好几周。Tail Workers 和 Analytics Engine 让我们在几天内就运转起来了。
大规模调试分布式 Workers 比我们预期的要难。相关工具链不如传统服务器环境成熟。但运维简化带来的权衡是值得的。
当前限制
D1 每个数据库有 10GB 的限制。这对大多数生产应用来说够用,但不适合数据密集型工作负载。
Workers 每个 HTTP 请求有 300 秒的 CPU 时间限制。长时间运行的任务需要异步模式或后台处理。
WebSocket 需要 Durable Objects 来维持持久状态。当前架构是纯请求-响应模式,因此实时功能(如在线状态或实时光标)需要额外的基础设施。
实时日志追踪目前仅支持 staging 环境。生产日志的保留和查询需要独立的存储和索引系统。
这些是我们目前在其中工作的平台约束。
未来规划
我们正在集成 Cron Triggers,用于定时后台任务,如数据库清理、报告生成和通知批处理。
对于实时协作,我们正在评估使用 Durable Objects 来处理 WebSocket、在线状态系统和状态同步。
为了支持数据密集型应用,我们正在添加 PostgreSQL 和 MySQL 支持,让租户 Workers 通过安全连接池访问外部数据库。
我们还在扩大 Analytics Engine 的使用范围,以支持更高层级的业务指标,如 API 端点热度、功能使用情况和错误模式分析。
边缘数据面已经在全球范围内扩展。这些工作聚焦于控制面能力的提升,以及随着底层原语不断演进而填补剩余的平台空白。
结语
我们在 Cloudflare Workers 上构建 YouBase,是因为我们不想在产品上线之前花六个月时间搞基础设施。两个月后,我们进入了生产环境,拥有毫秒级冷启动、边缘的一致性读取,以及自动化的可观测性。
仍然存在一些粗糙的边缘。调试分布式 Workers 比调试单体应用更难,一些平台限制需要变通方案。我们正在为 Workers 目前还不完全适配的领域构建混合解决方案。
但自上线以来,我们从未需要重建核心基础设施。到目前为止,它承受住了我们为之设计的工作负载。当我们需要跨所有租户进行更新时,大约只用了 30 秒。这正是最关键的那个权衡。
技术附录:使用的 Cloudflare 技术
数据面技术栈:
- Cloudflare Workers – 基于 V8 隔离环境的边缘无服务器计算
- Workers for Platforms – 带 dispatch namespace 的多租户 Worker 部署
- Cloudflare D1 – 基于 SQLite 的边缘数据库,配合 Session API 实现一致性
- Cloudflare R2 – 兼容 S3 的对象存储,支持全球边缘访问
- Cloudflare Service Bindings – 低延迟 RPC 风格的 Worker 间通信
- Cloudflare KV – 用于域名路由的键值存储
- Tail Workers – 实时日志流式传输和可观测性
- Analytics Engine – 无限基数的指标支持 SQL 查询
控制面技术栈:
- 运行时: Go 配合 Hertz 框架
- 数据库: PostgreSQL 用于控制面状态
- 缓存: Redis 用于会话和速率限制
- 无服务器: AWS Lambda 用于异步任务
面向用户的框架:
- HTTP 框架: Hono(轻量级,针对边缘优化)
- ORM: Drizzle ORM(类型安全的 SQL,配合 D1 适配器)
- 认证: Better Auth,原生支持 D1


