AI 参与说明(Agent:Codex
/root):本文由 Agent 根据 Cloudflare 官方 Workers、WAF 与控制面 API 文档辅助整理,并对示例、链接和 Hugo 产物进行校验。资料核验日期为 2026-08-24;产品能力、套餐限制、API 和配额可能继续变化,部署前请复核文末官方来源。
Cloudflare Workers Rate Limiting API 是一个 Worker binding。代码执行到特定业务位置时,显式调用 env.LIMITER.limit({ key }) 检查并尝试消耗一次计数额度,再由应用决定继续处理还是返回 429。它最适合在昂贵操作之前,按用户、租户、API key、套餐、路由、模型或其他业务资源做短周期防滥用和流量整形。Workers Rate Limiting API
它不是精确的全局配额账本:计数按 Cloudflare location 隔离,更新是 permissive、eventually consistent 的,短时间突发可能略微超过配置值。余额扣减、按 token 计费、严格日/月额度和全局并发控制,应使用 Durable Objects、数据库或持久化账本实现。
先分清四个同名概念#
用户给出的 Cloudflare API rate limits 页面并不是用来保护应用接口的产品配置页。Cloudflare 文档中至少有四个容易混淆的概念:
| 名称 | 谁限制谁 | 配置位置 | 主要用途 |
|---|---|---|---|
| Cloudflare API rate limits | Cloudflare 限制用户、Dashboard、SDK 或自动化调用其 REST / GraphQL API | 不可由普通用户自行配置 | 保护 Cloudflare 控制面 API;调用方应处理 429 和配额响应头。 |
| Workers Rate Limiting API | 应用代码限制执行到 limit() 的业务动作 | Worker 的 ratelimits binding 和 TypeScript / JavaScript 代码 | 按用户、租户、套餐、路由或资源做业务感知限流。本文重点。 |
| WAF Rate Limiting Rules | Cloudflare 边缘安全层限制匹配 zone / account ruleset 的 HTTP 流量 | Dashboard、Rulesets API 或 Terraform | 登录防爆破、抓取与 API 滥用防护、源站保护;无需修改应用代码。 |
| Rate Limiting API(previous version) | 曾用于管理旧版 rate limits | /zones/:zone_id/rate_limits 端点自 2025-06-15 deprecated | 不用于新配置;已有集成应迁移到 Rulesets API。官方 deprecations 页面未给出 EOL 日期。 |
一句话概括:控制面 API limits 是“Cloudflare 限制你调用它”;Workers binding 是“你的代码决定何时限”;WAF Rules 是“边缘安全层按流量规则限”。
Workers Rate Limiting API 如何工作#
它不会自动拦截一个 Worker 的全部请求。只有代码实际调用 limit(),该次调用才会计数。因此可以先完成路由、方法、基本格式和身份校验,只让真正准备进入昂贵业务逻辑的动作消耗额度。
flowchart TB R["HTTP request"] --> W["若对应 zone / account 已配置:WAF 入口防滥用"] W --> C["Worker:路由与低成本校验"] C --> A["认证并取得可信 user / tenant / plan"] A --> L["Rate Limiting binding:按业务 key 调用 limit()"] L -->|"success: false"| X["应用返回 429"] L -->|"success: true"| Q["可选 DO / 数据库:检查严格额度或计费账本"] Q -->|"额度不足"| Y["返回业务配额错误"] Q -->|"通过或无需严格额度"| E["模型推理、数据库写入、导出等昂贵操作"]
调用只有一个输入字段和一个核心返回字段:
const { success } = await env.MY_RATE_LIMITER.limit({
key: "rl:v1:tenant:tenant_123:action:export",
});key可以是任意字符串,由应用定义计数维度。- 每执行一次
limit()就尝试消耗一次额度;它并不知道这是不是一个 HTTP 请求。 - 返回值只告诉代码
success。API 不会自动返回 HTTP429,也不会提供 remaining 或精确 reset time。 - 当前
simple是唯一支持的配置类型,窗口只支持 10 秒或 60 秒。
配置 binding#
Workers Rate Limiting API 的配置最低要求 Wrangler CLI 4.36.0。若要使用本地 Rate Limiting simulation,建议至少使用 Wrangler 4.119.0;该版本包含本地计数持久性修复。下面演示的配置目标是“同一模型、同一 Cloudflare location,每 60 秒允许 5 次 chat 动作”;由于生产计数是 permissive、eventually consistent 的,它不是高并发下绝不超过 5 次的硬上限。API 配置与 accuracy · Wrangler 4.119.0 release
{
"name": "rate-limit-demo",
"main": "src/index.ts",
"compatibility_date": "2026-08-24",
"ratelimits": [
{
"name": "MODEL_INFERENCE_LIMITER",
"namespace_id": "31001",
"simple": {
"limit": 5,
"period": 60
}
}
]
}字段含义如下:
| 字段 | 含义 |
|---|---|
name | 注入 env 的 binding 名称。 |
namespace_id | 账号内由自己分配的正整数标识,但配置类型是 string;它不是 Workers KV namespace,也不需要先创建存储资源。 |
simple.limit | 一个窗口内允许成功通过的 limit() 调用数。 |
simple.period | 窗口秒数,目前只能是 10 或 60。 |
同一账号内,两个 binding 即使属于不同 Workers,只要共享相同的 namespace_id 和 key,就会共享相应计数器。需要跨 Worker 统一策略时可以有意复用;策略、套餐、环境或计数域不应共享时,应分配不同的 namespace_id。不要把 production 的编号误用于 staging。
应用自己的免费与付费用户也可以配置成两个 binding,例如 FREE_USER_LIMITER 和 PAID_USER_LIMITER,各自使用独立的 namespace_id、limit,代码根据服务端已验证的 plan 选择对应 binding。这里的 free / paid 是应用用户套餐,不代表 Cloudflare 账号套餐;截至资料核验日,官方没有公布该 binding 独立的计费项或明确的 Cloudflare Free / Paid 可用性矩阵,常规 Worker request / CPU 计费仍适用,生产前应在目标账号验证。Workers pricing · Rate Limiting GA
可运行的 TypeScript 示例#
下面的 Worker 只限制 POST /v1/models/:modelId/chat。健康检查、未知路径和方法错误都不会调用 limiter;真正接入模型供应商时,把最后的演示响应替换成推理调用即可。为让示例自包含,代码手动声明了 RateLimit;实际 Wrangler 项目也可以运行 npx wrangler types 生成当前配置对应的环境类型。Wrangler types
interface RateLimit {
limit(options: { key: string }): Promise<{ success: boolean }>;
}
interface Env {
MODEL_INFERENCE_LIMITER: RateLimit;
}
const MODEL_CHAT_ROUTE = /^\/v1\/models\/([a-z0-9._-]+)\/chat$/;
function json(
body: unknown,
status: number,
headers: HeadersInit = {},
): Response {
return Response.json(body, { status, headers });
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === "/health") {
if (request.method === "HEAD") {
return new Response(null, { status: 200 });
}
if (request.method !== "GET") {
return json(
{ error: "method_not_allowed" },
405,
{ Allow: "GET, HEAD" },
);
}
return json({ ok: true }, 200);
}
const match = url.pathname.match(MODEL_CHAT_ROUTE);
if (!match) {
return json({ error: "not_found" }, 404);
}
if (request.method !== "POST") {
return json(
{ error: "method_not_allowed" },
405,
{ Allow: "POST" },
);
}
const modelId = match[1]!;
const key = `rl:v1:model:${modelId}:action:chat`;
const { success } = await env.MODEL_INFERENCE_LIMITER.limit({ key });
if (!success) {
console.warn(JSON.stringify({
event: "rate_limited",
policy: "model_inference",
modelId,
}));
return json(
{ error: "rate_limit_exceeded" },
429,
{
"Cache-Control": "no-store",
"Retry-After": "60",
},
);
}
return json({ accepted: true, modelId }, 200);
},
};这里的 Retry-After: 60 是应用采用的保守提示,不是 limit() 返回的精确 reset time。业务若需要给客户端显示准确剩余额度和重置时刻,就需要自己维护可查询的配额状态。
本地运行:
npx wrangler --version
npx wrangler dev另一个终端连续调用六次:
for i in 1 2 3 4 5 6; do
curl -s -o /dev/null -w "%{http_code}\n" \
-X POST http://localhost:8787/v1/models/demo/chat
done紧密连续执行时,预期前五次返回 200,第六次返回 429。Wrangler / Vite 的本地开发支持 Rate Limiting simulation,默认不会消耗已部署 Worker 的计数;Rate Limiting 当前不支持 per-binding remote connection。
早于 Wrangler 4.119.0 的本地 Miniflare 模拟有一个已知问题:内部 Durable Object 空闲约 10–15 秒并被回收后,rate limit 计数可能在窗口结束前丢失;相同 namespace_id、不同 period 的本地 binding 也可能互相重置。Cloudflare 已在 Wrangler 4.119.0 所带的 Miniflare 版本中修复这两点。即使使用已修复版本,本地模拟仍主要用于验证代码逻辑;生产 locality 和高并发宽松计数行为应在隔离的 staging 部署验证。Rate Limiting 当前不支持 per-binding remote connection;legacy wrangler dev –remote 虽支持该 binding,但不应拿 production 计数做普通开发测试。问题说明 · 修复 PR #14968 · Wrangler 4.119.0 release
key 决定“限制谁的什么动作”#
推荐把 key 设计成带版本的稳定业务维度:
rl:v1:user:<opaque-user-id>:action:chat
rl:v1:tenant:<tenant-id>:route:reports-export
rl:v1:api-client:<client-id>:resource:search
rl:v1:model:<model-id>:action:image-generate设计时遵循这些原则:
- 用户、租户、plan 和权限必须来自服务端已验证的身份上下文,不能直接信任 query、body 或任意客户端 header 中自报的
userId。 - 优先使用不可变的内部 ID。不要把邮箱、手机号、access token、原始 API key 或其他 secrets / PII 直接放入 key;必要时使用已验证主体 ID 或单向摘要。
- 路由使用归一化模板或动作名,例如
reports-export,不要使用包含随机 ID、时间戳和任意 query 的完整 URL,否则每次请求可能落入新桶而绕过限制。 - IP 和国家/地区不适合作为已认证用户的主 key。移动网络、NAT 和隐私代理会让许多正常用户共享 IP;匿名流量的 IP / bot 防护优先交给 WAF。
- 一个组合 key 只限制这个维度的交集。若要同时执行“每租户 1,000 次/分钟”和“每用户 50 次/分钟”,应使用两个独立 binding 和两次
limit(),而不是把 tenant 与 user 拼成一个 key 后误以为两层额度都已实现。
调用顺序也是业务语义。先检查 tenant、再检查 user 时,tenant 计数会包含后来被 user policy 拒绝的尝试;API 没有 refund 或 decrement。防滥用通常应该统计尝试次数,但“只对最终成功业务扣额度”属于账本问题,不应强行用这个 binding 实现。
哪些业务适合限流#
| 业务 | 推荐维度 | Workers binding 是否合适 | 还需要什么 |
|---|---|---|---|
| 已认证 REST / GraphQL 操作 | user / tenant / API client + 归一化 action | 很合适 | WAF 先挡明显恶意流量;GraphQL 的复杂度或成本额度另行计算。 |
| 免费版与付费版调用频率 | 服务端确认的 plan + user / tenant | 很合适 | 每个 policy 使用独立 binding 和 namespace_id。 |
| AI chat、image generation、embedding、tool execution | user / tenant + model + action | 适合短周期防滥用和削峰 | token、金额、credits 和供应商全局配额用 DO / 数据库账本。 |
| 登录尝试 | 账号标识摘要 + action | 适合应用层补充 | WAF 先按路径、IP 或安全信号防爆破;避免泄露账号是否存在。 |
| 注册、验证码、密码重置 | 账号标识摘要 / verified session + action | 适合短周期限制 | 短信、邮件成本若必须严格受控,应再加全局持久配额。 |
| 搜索、爬取、公开 API | API client / session + route | 已有稳定身份时合适 | 匿名抓取、bot 和 IP abuse 优先使用 WAF Rate Limiting Rules。 |
| 文件上传、导出、报表、浏览器或 Sandbox job | user / tenant + action | 适合在昂贵任务创建前限流 | 任务排队、并发上限和 backpressure 使用 Queues / DO。 |
| Webhook 接收 | 验签后的 sender / tenant + event type | 适合限制已识别发送方 | 验签前先由 WAF 做粗粒度保护;重试和幂等仍需独立实现。 |
| 上游模型或第三方 API 保护 | provider / model / route | 适合每个 location 内削峰 | 供应商给的是全局硬 QPS 时,使用中心协调器,不能只依赖本地计数。 |
| 余额、库存、计费、日/月套餐额度 | account + ledger entry | 不合适 | 使用 DO / D1 等持久事务状态,并保留审计记录。 |
| 同时运行任务数、连接数 | tenant / resource | 不合适 | 这是 concurrency control,不是 10/60 秒请求速率;使用 DO、Queues 或专用调度器。 |
对“应用模型列表”这类场景,通常不需要把读取目录本身当作核心限流对象:GET /models 是可缓存、读多写少的请求,优先用 Workers Cache / KV 分发,并由 WAF 处理匿名抓取。真正应使用业务 binding 的往往是 chat、image-generate、embedding、regenerate 和 tool execution 等会消耗模型或第三方资源的动作;严格 credits 仍进入持久账本。
Rate Limiting binding 的每次检查权重固定为一个计数单位,没有“本次消耗 8,000 tokens”这样的 weight 参数。因此模型 token、图片尺寸、报表复杂度和金额不能直接映射成精确额度。
Workers binding、WAF 与 Durable Objects 如何组合#
生产环境通常采用分层方案:
- 对已经配置相应 zone rule,或 Enterprise account-level rate limiting ruleset 的流量,WAF Rate Limiting Rules 可以处理无需业务代码的入口保护,例如登录路径、恶意 IP、异常 header、抓取和源站流量。WAF rule 由 request expression、counting characteristics、period、threshold 与 mitigation action 等组成;可用字段、动作、周期和作用域受套餐影响。WAF Rate Limiting Rules
- Workers Rate Limiting API 在 Worker 启动后,根据鉴权得到的 user、tenant、plan、route 或 model 做业务感知的短周期限流,在调用数据库、AI 模型和第三方 API 之前快速拒绝。
- Durable Objects 或数据库维护必须全局准确、可查询、可审计的状态,例如 credits、按日/月额度、计费、库存和并发 lease。一个业务主体或资源可映射到一个 DO,以获得串行化更新边界。
WAF Rate Limiting Rules 的计数同样按 Cloudflare data center 划分,基础设施过载时还可能 fail open,因此它也不是精确账本;它的优势在于 Worker 业务代码之外的规则匹配与 mitigation action。WAF request rate calculation · WAF fail-open behavior
Workers Rate Limiting API 的底层计数器缓存在执行 Worker 的同一机器,并异步同步到同一 Cloudflare location 的 backing store,因此调用不会引入有意义的网络延迟。代价是它只在当前 location 内生效,并且故意采用宽松的最终一致模型。同一 key 在 Sydney 达到上限,不会同时耗尽其他 location 的独立桶。Workers Rate Limiting locality、performance 与 accuracy
这也解释了为什么 Workers KV 不适合替代它:KV 的 eventual consistency、每 key 写频率和 read-modify-write 能力都不适合实时计数;需要准确协调时应直接选 DO,而不是在 KV 上自制计数器。
监控与运维#
Rate Limiting bindings 当前不会在 Cloudflare Dashboard 中提供独立的可视化指标。至少应做到:Workers Rate Limiting monitoring
- 在 Worker 返回
429时记录结构化事件,通过 Workers Logs 和 Traces 查询。 - 需要趋势、policy / route / model 分组和告警时,向 Workers Analytics Engine 写入自定义
rate_limiteddatapoint。 - 不记录原始 API key、access token、邮箱、手机号或其他敏感 key;使用 policy 名称、归一化 action 和不透明主体标识。
- 区分 WAF 拒绝、Worker binding 拒绝、上游
429和 Cloudflare 控制面 API429,否则排障时会把四类问题混在一起。 - 根据真实峰值、成功率、重试行为和上游容量逐步调整阈值;先在 staging 和低风险 policy 验证,不把示例中的
5/min当作生产建议。
用户所给链接实际说明什么#
Cloudflare API rate limits 限制的是调用 Cloudflare 控制面 API 的客户端,整理时的主要配额如下:
| 类型 | 当前文档值 |
|---|---|
| Client API per user / account token | 1,200 次 / 5 分钟 |
| Client API per IP | 200 次 / 秒 |
| GraphQL | 按 query cost 变化,最高 320 次 / 5 分钟 |
| User API token quota | 50 个 |
| Account API token quota | 500 个 |
其中 user scope 的 1,200 次 / 5 分钟限制会累计同一用户通过 Dashboard、API key 和 user API token 发起的调用;account API token 则按该 account token 计算同样的窗口配额。超过相应限制后,后续五分钟的 API 调用会收到 HTTP 429;部分 Cache Purge、GraphQL、Rulesets 和 Lists API 还有各自限制。
Cloudflare REST API 会返回:
Ratelimit:各限制项的 remaining quota 与距离窗口重置的时间。Ratelimit-Policy:quota 和 window policy。retry-after:超限后距离恢复容量的秒数,只在超过限制时返回。
自动化脚本应读取这些 header,遵循 retry-after,并使用带 jitter 的退避、缓存、批量操作和并发上限,不能立即无限重试。Cloudflare 官方 SDK 会根据这些 header 自动 back off。它们与应用自行返回的 Retry-After 不是同一套计数。
选型结论#
- 需要“Worker 代码运行到某个业务动作时,按稳定业务 key 做 10 秒或 60 秒限流”:使用 Workers Rate Limiting API。
- 需要“在应用代码之外保护 HTTP 入口、阻止爆破、抓取和明显滥用”:使用 WAF Rate Limiting Rules。
- 需要“全球严格、可查询、可退款、可审计或按不同成本扣减”:使用 Durable Objects / 数据库账本。
- 需要“调用 Cloudflare REST / GraphQL API 不触发平台配额”:处理用户所给页面中的控制面 API limits 和响应头,而不是创建 Worker binding。
通用的固定窗口、滑动窗口、漏桶和令牌桶原理,可继续阅读 实现限流的几种方案。
官方来源#
- Workers Rate Limiting API
- Supported bindings per development mode
- workers-sdk:旧版本地 rate limit 计数提前重置问题 · 修复 PR #14968 · 包含修复的 Wrangler 4.119.0 release
- WAF Rate Limiting Rules
- WAF request rate calculation · WAF troubleshooting
- Create a WAF rate limiting rule via Rulesets API
- Cloudflare API rate limits
- Cloudflare API deprecations
- Workers pricing · Rate Limiting binding GA