Cloudflare Workers Rate Limiting API:用法、业务维度与选型边界

This article is extracted from the chat log with AI. Please identify it with caution.

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 limitsCloudflare 限制用户、Dashboard、SDK 或自动化调用其 REST / GraphQL API不可由普通用户自行配置保护 Cloudflare 控制面 API;调用方应处理 429 和配额响应头。
Workers Rate Limiting API应用代码限制执行到 limit() 的业务动作Worker 的 ratelimits binding 和 TypeScript / JavaScript 代码按用户、租户、套餐、路由或资源做业务感知限流。本文重点。
WAF Rate Limiting RulesCloudflare 边缘安全层限制匹配 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 不会自动返回 HTTP 429,也不会提供 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窗口秒数,目前只能是 1060

同一账号内,两个 binding 即使属于不同 Workers,只要共享相同的 namespace_idkey,就会共享相应计数器。需要跨 Worker 统一策略时可以有意复用;策略、套餐、环境或计数域不应共享时,应分配不同的 namespace_id。不要把 production 的编号误用于 staging。

应用自己的免费与付费用户也可以配置成两个 binding,例如 FREE_USER_LIMITERPAID_USER_LIMITER,各自使用独立的 namespace_idlimit,代码根据服务端已验证的 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

设计时遵循这些原则:

  1. 用户、租户、plan 和权限必须来自服务端已验证的身份上下文,不能直接信任 query、body 或任意客户端 header 中自报的 userId
  2. 优先使用不可变的内部 ID。不要把邮箱、手机号、access token、原始 API key 或其他 secrets / PII 直接放入 key;必要时使用已验证主体 ID 或单向摘要。
  3. 路由使用归一化模板或动作名,例如 reports-export,不要使用包含随机 ID、时间戳和任意 query 的完整 URL,否则每次请求可能落入新桶而绕过限制。
  4. IP 和国家/地区不适合作为已认证用户的主 key。移动网络、NAT 和隐私代理会让许多正常用户共享 IP;匿名流量的 IP / bot 防护优先交给 WAF。
  5. 一个组合 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 executionuser / tenant + model + action适合短周期防滥用和削峰token、金额、credits 和供应商全局配额用 DO / 数据库账本。
登录尝试账号标识摘要 + action适合应用层补充WAF 先按路径、IP 或安全信号防爆破;避免泄露账号是否存在。
注册、验证码、密码重置账号标识摘要 / verified session + action适合短周期限制短信、邮件成本若必须严格受控,应再加全局持久配额。
搜索、爬取、公开 APIAPI client / session + route已有稳定身份时合适匿名抓取、bot 和 IP abuse 优先使用 WAF Rate Limiting Rules。
文件上传、导出、报表、浏览器或 Sandbox jobuser / 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 的往往是 chatimage-generateembeddingregenerate 和 tool execution 等会消耗模型或第三方资源的动作;严格 credits 仍进入持久账本。

Rate Limiting binding 的每次检查权重固定为一个计数单位,没有“本次消耗 8,000 tokens”这样的 weight 参数。因此模型 token、图片尺寸、报表复杂度和金额不能直接映射成精确额度。

Workers binding、WAF 与 Durable Objects 如何组合#

生产环境通常采用分层方案:

  1. 对已经配置相应 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
  2. Workers Rate Limiting API 在 Worker 启动后,根据鉴权得到的 user、tenant、plan、route 或 model 做业务感知的短周期限流,在调用数据库、AI 模型和第三方 API 之前快速拒绝。
  3. 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_limited datapoint。
  • 不记录原始 API key、access token、邮箱、手机号或其他敏感 key;使用 policy 名称、归一化 action 和不透明主体标识。
  • 区分 WAF 拒绝、Worker binding 拒绝、上游 429 和 Cloudflare 控制面 API 429,否则排障时会把四类问题混在一起。
  • 根据真实峰值、成功率、重试行为和上游容量逐步调整阈值;先在 staging 和低风险 policy 验证,不把示例中的 5/min 当作生产建议。

用户所给链接实际说明什么#

Cloudflare API rate limits 限制的是调用 Cloudflare 控制面 API 的客户端,整理时的主要配额如下:

类型当前文档值
Client API per user / account token1,200 次 / 5 分钟
Client API per IP200 次 / 秒
GraphQL按 query cost 变化,最高 320 次 / 5 分钟
User API token quota50 个
Account API token quota500 个

其中 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。

通用的固定窗口、滑动窗口、漏桶和令牌桶原理,可继续阅读 实现限流的几种方案

官方来源#

本文共 5786 字,创建于 Aug 24, 2026

相关标签: Cloud, DevOps, TypeScript, ByAI