Back to Blog
Lesson 27 of the Cloudflare: Cloudflare for Developers: DNS to CDN course
Cloud NativeAugust 4, 20264 min read

Rate Limiting Basics: Protecting Your Apps with Cloudflare

Rate limiting is your first line of defense against abuse. Learn how to configure Cloudflare WAF and Worker-based throttling to secure your traffic.

Rate LimitingWAFSecurityWorkersAPITrafficCloudflare
Close-up view of Facebook app on a modern smartphone, emphasizing technology.

Previously in this course, we implemented Authentication Fundamentals to ensure only valid users access our API. While authentication keeps unauthorized users out, it doesn't prevent authorized users (or malicious bots) from overwhelming your services. In this lesson, we’ll implement Rate Limiting to control the volume of traffic reaching your origin, ensuring system stability and preventing resource exhaustion.

What is Rate Limiting?

At its core, rate limiting is the practice of restricting the number of requests a user (identified by IP, session, or API key) can make within a specific time window. Without it, a single buggy script or a malicious actor performing a brute-force attack can spike your CPU usage, drain your D1 database connections, or blow through your cloud spend.

When a limit is exceeded, the server responds with an HTTP 429 Too Many Requests status code. This signals to the client that they need to "back off" and wait before retrying.

Configuring Cloudflare WAF Rate Limiting

The easiest way to apply protection is via the Cloudflare WAF (Web Application Firewall). This happens at the edge, meaning the request is blocked before it even touches your Worker or database.

  1. Log in to the Cloudflare Dashboard.
  2. Navigate to Security > WAF > Rate limiting rules.
  3. Click Create rule.
  4. Define your criteria:
    • Rule Name: API-Limit-General
    • If incoming requests match: Select your API path (e.g., hostname equals api.yourdomain.com).
    • Rate limit: Set the threshold (e.g., 100 requests per 1 minute).
    • Action: Choose "Block" or "Managed Challenge" (the latter is often better for user experience, as it allows legitimate users to solve a puzzle instead of being hard-blocked).

Implementing Custom Rate Limits in a Worker

While WAF rules are great for global traffic, sometimes you need granular, logic-based control—for example, allowing "Premium" users higher limits than "Free" users. We can achieve this using Cloudflare Rate Limiting for Workers.

You will need to use the RateLimit object provided by the Cloudflare Workers runtime. Here is a simple implementation for our running project:

JAVASCRIPT
export default {
  async fetch(request, env, ctx) {
    // 1. Define the limit: 5 requests per minute per IP
    const { success } = await env.MY_RATE_LIMITER.limit({ key: request.headers.get("CF-Connecting-IP") });

    if (!success) {
      return new Response("Too Many Requests", { 
        status: 429,
        headers: { "Retry-After": "60" } 
      });
    }

    // Continue with your normal logic
    return new Response("Request processed");
  }
}

Note: You must define the MY_RATE_LIMITER binding in your wrangler.toml file to point to a Rate Limit resource.

Handling 429 Status Codes

When a client receives a 429, it is their responsibility to stop sending requests. As an API developer, you should always include the Retry-After header. This tells the client exactly how many seconds they should wait before trying again.

Best practices for handling 429s:

  • Exponential Backoff: If you are writing a client that calls this API, don't retry immediately. Wait 1s, then 2s, then 4s, and so on.
  • Graceful Failure: In your UI, don't just show a blank screen. Detect the 429 and show a friendly message like "We're receiving a lot of requests right now, please try again in a minute."

Hands-on Exercise

  1. Create a WAF Rate Limiting rule in your dashboard for a specific path (like /api/data). Set it to a very low number (e.g., 5 requests per minute).
  2. Use curl to hit that endpoint repeatedly from your terminal: for i in {1..10}; do curl -I https://yourdomain.com/api/data; done
  3. Observe the response headers. Once you hit the limit, you should see the 429 status code.

Common Pitfalls

  • Trusting Client IPs: Never rely on X-Forwarded-For headers set by the client. Always use Cloudflare's CF-Connecting-IP or the standard request.headers.get("cf-connecting-ip") to identify the user.
  • Too Strict Limits: Setting limits too low will frustrate legitimate users. Always monitor your logs to ensure you aren't blocking real traffic.
  • Ignoring the Cache: Rate limits are often applied to the origin. If you have assets cached at the edge, they might not count against your limit. Be intentional about whether your limit applies to cached or dynamic traffic.

FAQ

Q: Should I use WAF or Worker rate limiting? A: Use WAF for broad, infrastructure-level protection (e.g., blocking scrapers). Use Workers for application-specific logic (e.g., different tiers of service).

Q: Does a 429 response count against my bill? A: Cloudflare Workers are billed by the request. While a 429 response is cheaper than a full database-heavy request, it is still a request execution.

Q: Can I reset the rate limit manually? A: Generally, no. Rate limits are time-window based and managed by the platform. You must wait for the window to reset.

Recap

We've covered how to protect your application by implementing rate limiting at the WAF level and programmatically within your Worker. By returning 429 status codes and respecting Retry-After headers, you create a robust, resilient system that handles traffic spikes gracefully.

Up next: We will dive into WAF Custom Rules to gain even more control over exactly who can access your endpoints based on geography and IP reputation.

Similar Posts