Rate Limiting
Rate limiting is one of the simplest and most important security measures you can add to your app. Yet AI-generated code almost never includes it unless you specifically ask.
This page explains what rate limiting is, why it matters, and how to make sure your app has it.
What Is Rate Limiting?
Rate limiting means restricting how many times someone can do something in a given time period.
Think of it like a coffee shop that serves one customer at a time. Without rate limiting, a single customer could order 1,000 coffees and block everyone else. With rate limiting, each customer gets their turn.
In your app, rate limiting typically applies to:
- Login attempts
- Form submissions
- API requests
- File uploads
- Account creation
Why Your App Needs Rate Limiting
Without Rate Limiting
| Attack | What Happens | Impact |
|---|---|---|
| Brute force login | Attacker tries 10,000 passwords per minute | Any account can be hacked |
| Form spam | Bot submits your contact form 1,000 times | Your inbox is flooded, server overloaded |
| API abuse | Attacker calls your API 100,000 times | You pay for the bandwidth/API costs |
| Account creation spam | Bot creates 10,000 fake accounts | Your user database is polluted |
| Denial of service | Attacker sends millions of requests | Your server crashes, app goes down |
With Rate Limiting
| Scenario | What Happens |
|---|---|
| Brute force login | After 5 failed attempts, user must wait 1 minute |
| Form spam | After 3 submissions per hour, further submissions are blocked |
| API abuse | After 100 requests per minute, API returns "too many requests" |
| Account creation spam | After 3 accounts per IP per day, creation is blocked |
| Denial of service | Rate limiter absorbs the attack, legitimate users are unaffected |
Where to Apply Rate Limiting
Critical: Apply Rate Limiting Here
| Endpoint | Suggested Limit | Why |
|---|---|---|
| Login | 5 attempts per 15 minutes per IP | Prevent brute force password guessing |
| Registration | 3 accounts per IP per day | Prevent fake account creation |
| Password reset | 3 requests per hour per email | Prevent password reset spam |
| Contact forms | 3 submissions per IP per hour | Prevent form spam |
| File uploads | 10 uploads per user per hour | Prevent storage abuse |
| API endpoints | 100 requests per minute per user | Prevent API abuse |
Important: Apply Rate Limiting Here
| Endpoint | Suggested Limit | Why |
|---|---|---|
| Search | 30 requests per minute per user | Prevent excessive database queries |
| Data export | 1 export per hour per user | Prevent server load from large exports |
| Comment posting | 10 comments per hour per user | Prevent comment spam |
How Rate Limiting Works
Simple Approach: IP-Based
Track requests by IP address. If an IP exceeds the limit, block further requests.
Pros: Simple to implement, no user accounts needed Cons: Users behind the same IP (office, school, VPN) share limits
Better Approach: User-Based
Track requests by logged-in user ID.
Pros: Fair per-user limits Cons: Requires authentication, doesn't protect login page
Best Approach: Combined
Use both IP-based and user-based limits.
For login: IP-based (attacker isn't logged in) For API: User-based (logged-in users have higher limits) For forms: IP-based (no authentication needed)
What Happens When Rate Limit Is Exceeded
Your app should respond with:
HTTP Status: 429 Too Many Requests
Response: {
"error": "Too many requests. Please try again in 15 minutes.",
"retry_after": 900
}
The response should:
- Use HTTP status 429 (standard for rate limiting)
- Include a clear, user-friendly error message
- Tell the user when they can try again
- Not reveal technical details about your rate limiting implementation
How to Add Rate Limiting to Your App
What to Ask Your AI
When building any feature that accepts user input, add this to your prompt:
Security requirement: Add rate limiting to this endpoint.
- Limit: [X] requests per [time period] per [IP/user]
- Response: HTTP 429 with message "Too many requests. Please try again later."
- Use [your framework's] built-in rate limiting if available, or implement with [library].
Framework-Specific Rate Limiting
Most frameworks have built-in or easy-to-add rate limiting:
| Framework | How to Add Rate Limiting |
|---|---|
| Next.js | Use express-rate-limit or Vercel's WAF rules |
| Laravel | Built-in RateLimiter facade |
| Django | Use django-ratelimit package |
| Express | Use express-rate-limit package |
| Ruby on Rails | Built-in Rack::Attack |
| FastAPI | Use slowapi package |
| Flask | Use Flask-Limiter package |
Example Prompt for Express/Node.js
Add rate limiting to the login endpoint using express-rate-limit.
Requirements:
- Limit: 5 attempts per 15 minutes per IP
- Response: HTTP 429 with JSON { error: "Too many login attempts. Please try again in 15 minutes." }
- Include Retry-After header with seconds until reset
- Store rate limit data in memory (or Redis for production)
- Log rate limit events for monitoring
Rate Limiting Checklist
- Login endpoint has rate limiting (5 attempts per 15 minutes)
- Registration endpoint has rate limiting (3 per day per IP)
- Password reset endpoint has rate limiting (3 per hour)
- Contact/feedback forms have rate limiting (3 per hour)
- File upload endpoints have rate limiting
- API endpoints have rate limiting (100+ per minute)
- Rate limited requests return HTTP 429
- Error messages are user-friendly
- Rate limit data persists across server restarts (use Redis or database)
- Rate limiting is tested (try exceeding the limit)
- Rate limiting logs are monitored for attack patterns
The Bottom Line
Rate limiting is the difference between an app that can handle abuse and an app that collapses under it.
It's one of the simplest security measures to implement, yet AI-generated code almost never includes it. Make "add rate limiting" a standard part of every prompt for any endpoint that accepts user input.
Without rate limiting, your login page is a door with no lock. Your contact form is an open mailbox for spam. Your API is a free-for-all. Add rate limiting before you launch.