Skip to content

Rate Limiting -- Configure and Tune

DodaTech 8 min read

In this tutorial, you'll learn about Rate Limiting. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Cloudflare Rate Limiting protects your application from abuse by tracking how often each client makes requests and taking action when a threshold is exceeded. You define a rate limit rule with a request count, time window, and action -- when a client exceeds the limit, Cloudflare blocks, challenges, or throttles subsequent requests from that client for a specified duration.

Why Rate Limiting Matters

Without Rate Limiting, a single attacker or misconfigured script can overwhelm your application with requests. Brute force login attempts, API scraping, credit card testing, and comment spam are all forms of abuse that Rate Limiting mitigates. Unlike a WAF which inspects payload content, Rate Limiting looks at request velocity -- how fast, how many, and from whom. It is your first line of defense against resource exhaustion and account takeover attacks.

Real-World Use Case

A ticketing platform experienced a bot attack during a popular event sale. Bots sent 10,000 requests per second to the checkout API, overwhelming the origin server and causing legitimate users to see 503 errors. The team deployed a Rate Limiting rule that allowed a maximum of 20 POST requests per minute per IP to the checkout endpoint. Bots were blocked after exceeding the limit, and legitimate users completed their purchases normally. The platform sold out in 15 minutes without further issues.

Rate Limiting Flow

flowchart TD
    R[Client Request] --> T[Track Request Count]
    T --> C{Count > Threshold?}
    C -->|No| F[Forward to Origin]
    C -->|Yes| D{Duration Elapsed?}
    D -->|No| A[Apply Action - Block / Challenge]
    D -->|Yes| R
    
    subgraph "Rate Limit Window"
        T
        W[Time Window - 60s / 120s / 600s]
    end
    
    style C fill:#e67e22,color:#fff
    style A fill:#e74c3c,color:#fff
    style F fill:#27ae60,color:#fff

Cloudflare tracks requests per client (by IP or other identifier) within a sliding time window. When the count exceeds the threshold, subsequent requests trigger the configured action. After the duration period, the counter resets and the client can make requests again.

Creating a Rate Limiting Rule via API

# Create a rate limiting rule for the login endpoint
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rate_limits" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "description": "Rate limit login endpoint",
    "threshold": 10,
    "period": 60,
    "action": "block",
    "action_expiry": 300,
    "match": {
      "request": {
        "url": "https://example.com/api/login",
        "methods": ["POST"],
        "schemes": ["HTTPS"]
      },
      "response": {}
    }
  }' | python3 -m json.tool
# Expected output:
# {
#   "result": {
#     "id": "rate-limit-rule-1",
#     "description": "Rate limit login endpoint",
#     "threshold": 10,
#     "period": 60,
#     "action": "block",
#     "action_expiry": 300
#   },
#   "success": true
# }

This rule limits POST requests to /api/login to 10 per 60 seconds per client. When the threshold is exceeded, the client is blocked for 300 seconds (5 minutes). The period is in seconds. The action_expiry defines how long the block lasts after the threshold is crossed.

API Endpoint Protection with Burst Handling

# Create a rate limiting rule with burst allowance for an API
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rate_limits" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "description": "Protect public API v3 endpoint",
    "threshold": 100,
    "period": 120,
    "action": "block",
    "action_expiry": 60,
    "match": {
      "request": {
        "url": "https://api.example.com/v3/*",
        "methods": ["GET", "POST", "PUT", "DELETE"],
        "schemes": ["HTTPS"]
      },
      "response": {}
    }
  }' | python3 -m json.tool
# Expected output:
# {
#   "result": {
#     "id": "rate-limit-rule-2",
#     "threshold": 100,
#     "period": 120
#   },
#   "success": true
# }

This rule allows 100 requests per 120 seconds to the API v3 endpoint. The wildcard * in the URL matches all paths under /v3/. The 60-second action expiry means clients are only briefly blocked, allowing legitimate clients that hit the limit sporadically to recover quickly.

Listing and Monitoring Rate Limit Rules

# List all rate limiting rules
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rate_limits" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for rule in data['result']:
    print(f'ID: {rule[\"id\"]}, Thresh: {rule[\"threshold\"]}/{rule[\"period\"]}s, Action: {rule[\"action\"]}, URL: {rule.get(\"match\", {}).get(\"request\", {}).get(\"url\", \"N/A\")}')
"
# Expected output:
# ID: rate-limit-rule-1, Thresh: 10/60s, Action: block, URL: https://example.com/api/login
# ID: rate-limit-rule-2, Thresh: 100/120s, Action: block, URL: https://api.example.com/v3/*

List all Rate Limiting rules to audit your configuration. Review the thresholds and periods to ensure they match your traffic patterns. Rules with very low thresholds may block legitimate users during traffic spikes.

Simulating Rate Limit Trigger

# Simulate rapid requests to trigger rate limiting
for i in $(seq 1 15); do
  curl -s -o /dev/null -w "Request $i: HTTP %{http_code}\n" \
    -X POST "https://example.com/api/login" \
    -H "Content-Type: application/json" \
    -d '{"username":"test","password":"test"}'
done
# Expected output:
# Request 1: HTTP 200
# Request 2: HTTP 200
# ...
# Request 11: HTTP 429
# Request 12: HTTP 429
# ...

After exceeding the threshold, subsequent requests return HTTP 429 (Too Many Requests). The response includes headers indicating the rate limit status. Legitimate clients should back off when they receive a 429 response. This is the standard HTTP status code for Rate Limiting.

Updating and Deleting Rate Limit Rules

# Update an existing rate limiting rule (change threshold)
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rate_limits/RULE_ID" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "description": "Rate limit login endpoint - tuned",
    "threshold": 20,
    "period": 60,
    "action": "block",
    "action_expiry": 120,
    "match": {
      "request": {
        "url": "https://example.com/api/login",
        "methods": ["POST"],
        "schemes": ["HTTPS"]
      },
      "response": {}
    }
  }' | python3 -m json.tool

# Delete a rate limiting rule
curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rate_limits/RULE_ID" \
  -H "Authorization: Bearer YOUR_API_TOKEN" | python3 -m json.tool
# Expected output:
# {
#   "result": {
#     "id": "rate-limit-rule-id"
#   },
#   "success": true
# }

Use PUT to update existing rules and DELETE to remove them. When updating, you must send the full rule definition -- partial updates are not supported. Always test updated rules with a log action first, then switch to block.

Common Errors and Troubleshooting

Rate Limiting Not Triggering

If requests are not being rate limited, check that the URL pattern matches exactly. The URL must include the scheme (https://), hostname, and path. Wildcards match paths but not hostnames. Solution: verify the URL in the rule matches the actual request URLs shown in Cloudflare analytics.

False Positives from Shared IPs

Corporate networks, VPNs, and NAT gateways share a single public IP among many users. A rate limit that is appropriate for individual users may block entire offices. Solution: use a higher threshold for endpoints accessed from corporate IPs, or use Cloudflare Rate Limiting v2 with bot score integration to distinguish human users from bots.

Block Duration Too Long

If the action_expiry is too long, legitimate users who accidentally exceed the limit are blocked for an extended period. Solution: start with a short expiry (30-60 seconds) and increase only if abuse persists. Inform users with a 429 response that they should wait before retrying.

Rate Limiting Not Covering All Methods

By default, Rate Limiting rules apply to all HTTP methods. If you specify only POST in the methods array, GET requests are not counted. Solution: ensure the methods array includes all request types you want to track, or omit it to apply to all methods.

Analytics Not Showing Rate Limit Events

Rate limit events appear in Cloudflare analytics under Security > Events. If you see no events, the rule may not be matching any traffic, or the threshold may be too high. Solution: temporarily lower the threshold to 1 request per period to verify the rule triggers, then increase to the appropriate value.

Practice Questions

  1. What HTTP status code does Cloudflare return when a rate limit is exceeded?
  2. What is the purpose of the action_expiry field in a Rate Limiting rule?
  3. How does a shared corporate IP affect Rate Limiting and how can you mitigate it?

FAQ

Does Rate Limiting apply to cached requests?

No. Cloudflare Rate Limiting only applies to requests that reach the origin server. Requests served directly from Cloudflare's cache (cache hit) are not counted toward the rate limit threshold. This means static assets served from cache do not consume the client's rate limit budget.

Can I set different rate limits for authenticated vs unauthenticated users?

Cloudflare Rate Limiting identifies clients by IP address by default. For user-based Rate Limiting (distinguishing authenticated vs unauthenticated), use Cloudflare Rate Limiting v2 with custom fields. Alternatively, set a lower rate limit for the anonymous tier and a higher limit for authenticated users by configuring separate rules for different URL paths.

What happens to rate-limited requests at the origin?

Rate-limited requests are blocked at Cloudflare's edge and never reach your origin server. This is a key benefit -- Rate Limiting protects your origin from traffic surges and abusive requests before they consume your server resources. The origin only sees requests that pass the rate limit check.

Summary

Cloudflare Rate Limiting protects your application from abuse by tracking request velocity per client and taking action when thresholds are exceeded. Rules define a request count, time window, and action (block, challenge, or throttle). Rate Limiting is essential for login endpoints, APIs, search functionality, and any resource that could be abused by automated clients. Configure rules with appropriate thresholds, test with a log action first, and monitor analytics to tune for your traffic patterns. Rate Limiting combined with WAF rules provides comprehensive edge-level protection.

This guide is brought to you by the developers of Cloudflare, Cyber Security, and Doda Browser at DodaTech.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro