This site is not affiliated with or endorsed by Cloudflare, Inc. It showcases deployable experiments across most Cloudflare products.
Edge Platform

Rate Limiter Demo

Native Workers Rate Limiting binding with 429 responses and usage visualization - protect APIs at the edge without Redis

Demonstrates the native Workers Rate Limiting binding. GET /limited enforces per-key limits and returns 429 with Retry-After when exceeded. GET /status shows configured limits and demo usage counters stored in KV.

Features

  • GET /limited - Rate-limited endpoint (10 req / 60s per key)
  • GET /status?key= - View limit config and usage counters
  • 429 responses - Includes Retry-After header and RATE_LIMITED code
  • Per-key limiting - Defaults to client IP; override with ?key=

API Reference

GET /limited

Request the rate-limited resource.

key string (optional query)

Override rate limit key (max 128 chars). Defaults to CF-Connecting-IP.

Example Request

curl "https://your-worker.workers.dev/limited"
curl "https://your-worker.workers.dev/limited?key=demo-client"

Success Response

{
  "message": "Request allowed",
  "key": "203.0.113.1",
  "limit": 10,
  "periodSeconds": 60
}

Rate Limited Response (429)

{
  "error": "Rate limit exceeded",
  "code": "RATE_LIMITED",
  "key": "203.0.113.1",
  "retryAfterSeconds": 60
}

Response includes header: Retry-After: 60

GET /status

View rate limit configuration and demo usage counters.

key string (optional query)

Key to inspect. Defaults to client IP.

Example Request

curl "https://your-worker.workers.dev/status?key=demo-client"

Success Response

{
  "key": "demo-client",
  "config": { "limit": 10, "periodSeconds": 60 },
  "usage": {
    "key": "demo-client",
    "allowed": 7,
    "blocked": 3,
    "lastSeen": "2025-06-20T12:00:00.000Z"
  },
  "note": "Native Rate Limiting binding enforces limits per PoP..."
}

Use Cases

  • Learn the Workers Rate Limiting binding (limit() API)
  • Prototype API throttling before production WAF rules
  • Demonstrate 429 + Retry-After client handling

Limitations

  • Rate limits are enforced per PoP by the native binding
  • KV usage counters are for demo visualization only (not authoritative)
  • Configured limit: 10 requests per 60 seconds (see wrangler.json)

Use in your project

Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/rate-limiter-demo.

DependenciesNoneBindingsKV, Rate LimitingPlatformWorkers runtime
import type { Env, UsageRecord } from "../types/env";function usageKey(key: string): string {  return `usage:${key}`;}export async function recordUsage(env: Env, key: string, allowed: boolean): Promise<UsageRecord> {  const existingRaw = await env.USAGE.get(usageKey(key));  const existing = existingRaw    ? (JSON.parse(existingRaw) as UsageRecord)    : { key, allowed: 0, blocked: 0, lastSeen: new Date().toISOString() };  const updated: UsageRecord = {    ...existing,    allowed: existing.allowed + (allowed ? 1 : 0),    blocked: existing.blocked + (allowed ? 0 : 1),    lastSeen: new Date().toISOString(),  };  await env.USAGE.put(usageKey(key), JSON.stringify(updated), { expirationTtl: 3600 });  return updated;}export async function getUsage(env: Env, key: string): Promise<UsageRecord | null> {  const raw = await env.USAGE.get(usageKey(key));  return raw ? (JSON.parse(raw) as UsageRecord) : null;}export function resolveClientKey(request: Request, override?: string | null): string {  if (override?.trim()) return override.trim().slice(0, 128);  const ip = request.headers.get("CF-Connecting-IP") ?? request.headers.get("X-Forwarded-For");  return ip?.split(",")[0]?.trim() || "anonymous";}export function validateKey(input: string | undefined | null): string | null {  if (!input || typeof input !== "string") return null;  const trimmed = input.trim();  if (!trimmed || trimmed.length > 128) return null;  return trimmed;}

Deployment

Click the deploy button

Deploy to Cloudflare Workers

Configure KV

Create a KV namespace bound as USAGE. Rate limit binding is declared in wrangler.json.

Test rate limiting

for i in $(seq 1 12); do curl -s -o /dev/null -w "%{http_code}\n" "https://your-worker.workers.dev/limited"; done

Local Development

cd apps/experiments/rate-limiter-demo
npm install
npm run dev

Configuration

Binding / settingPurpose
RATE_LIMITERNative rate limiting (10 req / 60s)
USAGEKV namespace for demo usage counters

Cloudflare Features Used

On this page