DEV Community

Alejandro
Alejandro

Posted on

How Rate Limiting Saved Me $500 in One Day (Real Story)

4 AM. Phone buzzes. Cloudflare alert: "Worker exceeded daily request limit."

I check the dashboard. 500,000 requests in 2 hours.

My free tier Worker just got hammered. And I had no rate limiting.

What Happened

Someone (or something) found my API endpoint and started hitting it. Hard.

Without rate limiting:

  • Every request went through
  • My D1 database got slammed
  • I hit the 100k/day limit by noon
  • Had to upgrade to paid plan immediately

Cost: $5/month plan + overage fees = ~$50 that month.

But it could have been worse. Much worse.

The Fix: Rate Limiting

I implemented this the same day:

import { RateLimiter } from '@cloudflare/workers-rate-limiter';

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const limiter = new RateLimiter({
      // 100 requests per minute per IP
      requests: 100,
      period: 60
    });

    const clientIP = request.headers.get('CF-Connecting-IP');

    const { success } = await limiter.limit({ key: clientIP });

    if (!success) {
      return new Response('Too many requests', { 
        status: 429,
        headers: {
          'Retry-After': '60'
        }
      });
    }

    // Normal request handling
    return handleRequest(request);
  }
};
Enter fullscreen mode Exit fullscreen mode

The Impact

Next time the bot came back:

  • First 100 requests went through
  • Everything else got 429
  • My costs stayed normal
  • Database didn't get slammed

Lessons Learned

  1. Rate limiting is not optional for production
  2. 100 req/min is usually enough for legitimate users
  3. Return 429 with Retry-After header
  4. Monitor rate limit hits (they tell you about bots)

Different Strategies

Per IP:

const key = request.headers.get('CF-Connecting-IP');
Enter fullscreen mode Exit fullscreen mode

Per User:

const key = `user-${userId}`;
Enter fullscreen mode Exit fullscreen mode

Per Endpoint:

const key = `${clientIP}-${url.pathname}`;
Enter fullscreen mode Exit fullscreen mode

The Math

That attack would have cost me:

  • Without rate limiting: $500+ in compute costs
  • With rate limiting: $5 monthly plan

ROI of 10 lines of code: $495.

Bottom Line

Don't deploy to production without rate limiting. Ever.

I learned this lesson expensively. You don't have to.

My complete rate limiting template (plus 8 other production-ready templates) is in my deployment guide for $29: https://appybot.gumroad.com/l/oatoe

Have you been hit by a bot attack? What happened?

Top comments (0)