How to Set Up Rate Limiting

Rate limiting prevents abuse by restricting the number of requests from a single IP address within a time window. This guide covers common rate limiting scenarios.

Understanding Rate Limiting

Rate limiting tracks requests per IP address and blocks when thresholds are exceeded. Configuration includes:

  • Protected paths: URLs to monitor
  • Events per minute: Maximum requests allowed
  • Time window: 60 seconds (fixed)
  • Response: Block method (403, 404, drop)

Rate limits apply per source IP. Multiple users behind the same IP (corporate proxy, NAT) share the limit.

Protecting Login Pages

WordPress Login

Prevent brute force attacks on wp-login.php:

Configuration:

Rate Limiting: Enabled
Protected Paths: /wp-login.php
Events per minute: 5
Response: Drop

Rationale: – Legitimate users rarely need more than 5 login attempts per minute – Drop response wastes attacker resources – Protects against credential stuffing

Testing:

# Test legitimate login (should work)
curl -X POST https://example.com/wp-login.php \
  -d "log=username&pwd=password"

# Test rate limit (repeat 6+ times rapidly)
for i in {1..10}; do
  curl -w "Attempt $i: %{http_code}\n" -o /dev/null -s \
    https://example.com/wp-login.php
  sleep 1
done

Expected: First 5 attempts get response, subsequent attempts timeout (drop) or return 403.

Custom Admin Login

For custom admin panels:

Configuration:

Rate Limiting: Enabled
Protected Paths: /admin/login, /administrator/login
Events per minute: 10
Response: 403

Considerations: – Higher limit for internal tools with multiple quick operations – 403 response provides clear feedback – Monitor logs to verify legitimate use patterns

Protecting API Endpoints

Public API

Rate limit public API to prevent abuse:

Configuration:

Rate Limiting: Enabled
Protected Paths: /api/
Events per minute: 60
Response: 403

Rationale: – 60 requests per minute = 1 per second average – Legitimate API clients rarely exceed this – Prevents API scraping and abuse

Response Headers:

Clients receive standard HTTP 403 when rate limited. Consider implementing retry logic:

import time
import requests

def api_call_with_retry(url, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url)
        
        if response.status_code == 403:
            # Assume rate limit, wait and retry
            wait_time = (2 ** attempt) * 10
            time.sleep(wait_time)
            continue
            
        return response
    
    raise Exception("Max retries exceeded")

Authenticated API

Different limits for authenticated vs anonymous:

Anonymous API:

Protected Paths: /api/public/
Events per minute: 30
Response: 403

Authenticated API (use IP whitelist for known servers):

Protected Paths: /api/private/
Whitelist: [trusted-server-ips]
Events per minute: 300
Response: 403

Protecting Search Functionality

Search endpoints are commonly abused:

Configuration:

Rate Limiting: Enabled
Protected Paths: /search, /?s=
Events per minute: 20
Response: 403

Rationale: – Prevents search enumeration attacks – Reduces load from automated scanning – Legitimate users rarely search 20+ times per minute

Testing:

# Test search rate limit
for i in {1..25}; do
  echo "Search $i:"
  curl -s -o /dev/null -w "%{http_code}\n" \
    "https://example.com/?s=test$i"
  sleep 2
done

Expected: First 20 searches succeed, subsequent ones blocked.

Protecting Registration Pages

Prevent automated account creation:

Configuration:

Rate Limiting: Enabled
Protected Paths: /register, /wp-login.php?action=register
Events per minute: 3
Response: 403

Rationale: – Legitimate users register once – Very low limit acceptable – Prevents bot registration spam

Considerations: – May need to whitelist office IPs during user import – Monitor for legitimate users hitting limit – Consider CAPTCHA as alternative

Protecting Form Submissions

Contact forms and comment forms:

Configuration:

Rate Limiting: Enabled
Protected Paths: /wp-comments-post.php, /contact-form
Events per minute: 10
Response: 403

Rationale: – Prevents comment spam – Limits contact form abuse – Still allows legitimate rapid submissions

Advanced Configurations

Multiple Path Protection

Protect multiple endpoints with different limits:

Site-Wide Base Limit:

Protected Paths: /
Events per minute: 300
Response: 403

Login Endpoint:

Protected Paths: /wp-login.php
Events per minute: 5
Response: Drop

API Endpoint:

Protected Paths: /api/
Events per minute: 60
Response: 403

Most specific path wins. Request to /wp-login.php uses 5/min limit, not 300/min.

Graduated Response

Use different responses for different abuse levels:

Light Abuse:

Protected Paths: /api/
Events per minute: 60
Response: 403

Heavy Abuse:

Protected Paths: /wp-login.php
Events per minute: 5
Response: Drop

Drop response for login pages wastes more attacker resources than 403.

Temporary Whitelist

During legitimate high-volume operations:

  1. Note the source IP
  2. Add to Page Protection whitelist temporarily
  3. Perform operation
  4. Remove from whitelist

Example: Data migration, bulk operations, load testing.

Monitoring Rate Limiting

Check Security Logs

Review logs for rate limit triggers:

Dashboard Filters: – Filter by message: “rate limit” – Group by IP to identify repeat offenders – Check time distribution for patterns

Log Analysis:

Most rate-limited IPs:
203.0.113.45 - 1,247 blocks
198.51.100.30 - 892 blocks
192.0.2.15 - 456 blocks

Identify Legitimate Blocks

Signs legitimate users are being rate limited:

  • Support requests about “too many requests” errors
  • Logs show rate limits on normal business hours
  • Known good IPs being blocked
  • Specific users reporting issues

Solution: Increase limit or whitelist specific IPs.

Identify Attack Patterns

Attack indicators:

  • Rate limits triggered outside business hours
  • Consistent limits on login/admin endpoints
  • Geographic distribution (attacks from multiple countries)
  • Repeated patterns from same IP blocks

Response: Lower limits, change to drop response, or block IPs entirely.

Adjusting Rate Limits

Increasing Limits

If legitimate users are blocked:

  1. Review security logs for block patterns
  2. Identify specific legitimate use cases
  3. Increase limit by 50-100%
  4. Monitor for one week
  5. Adjust further if needed

Example: API at 60/min causing issues, increase to 120/min.

Decreasing Limits

If attacks continue:

  1. Review attack volume in logs
  2. Note attacker request rate
  3. Decrease limit to 50% of attack rate
  4. Monitor attack success rate
  5. Adjust further if attacks persist

Example: Login attacks at 20/min, decrease limit from 10/min to 5/min.

Per-Endpoint Tuning

Different endpoints have different legitimate use patterns:

Login: 3-5 requests/min (very low) API: 60-120 requests/min (moderate) Search: 10-20 requests/min (low-moderate) Public pages: 100-300 requests/min (high)

Tune each endpoint independently based on actual usage.

Common Scenarios

E-Commerce Checkout

Balance security and user experience:

Configuration:

Protected Paths: /checkout
Events per minute: 30
Response: 403

Rationale: – Users may refresh during payment processing – Some payment methods require multiple requests – Higher limit accommodates legitimate use – Still blocks automated card testing

Testing: Complete full checkout process multiple times rapidly.

Mobile App APIs

Mobile apps make frequent API calls:

Configuration:

Protected Paths: /api/mobile/
Events per minute: 120
Response: 403
Whitelist: [known-good-user-ips if applicable]

Considerations: – Mobile apps poll for updates – Users may trigger multiple operations – Background sync operations – Higher limits needed

Multi-User Environments

Corporate environments with shared IPs:

Problem: 100 users share one IP, 5/min limit = 0.05 requests per user per minute.

Solutions:

  1. Whitelist corporate IPs:
Page Protection whitelist: [corporate-ip]
  1. Increase limits significantly:
Events per minute: 500
  1. Use authentication-based rate limiting (application-level, not WAF)

Content Scraping Prevention

Prevent bulk content downloads:

Configuration:

Protected Paths: /
Events per minute: 100
Response: 403

Rationale: – Legitimate users browse ~1-2 pages per minute – Scrapers request 10-100+ pages per minute – 100/min allows headroom but blocks aggressive scraping

Additional Protection: – Enable bot protection – Block known scraper user agents – Use geographic blocking for regions with no legitimate users

Troubleshooting

Legitimate Users Blocked

Symptom: Users report “too many requests” errors during normal use.

Diagnosis: 1. Check security logs for user’s IP 2. Review request timestamps 3. Identify specific operations triggering limit

Solution: – Increase rate limit by 50-100% – Whitelist specific user IPs if identifiable – Review application behavior (excessive AJAX?)

Rate Limiting Not Effective

Symptom: Attacks continue despite rate limiting enabled.

Diagnosis: 1. Verify rate limiting is enabled and deployed 2. Check that correct paths are protected 3. Review logs to confirm limits are triggering 4. Check if attacker is rotating IPs

Solution: – Decrease rate limit threshold – Change response from 403 to Drop – Add geographic blocking – Consider blocking specific IP ranges

False Positive Spikes

Symptom: Sudden increase in rate limit blocks on legitimate traffic.

Diagnosis: 1. Check for application changes (new feature, marketing campaign) 2. Review request patterns in logs 3. Identify if specific feature causing issue

Solution: – Temporarily increase limits during high-traffic events – Whitelist known-good IPs – Optimize application to reduce request volume

Distributed Attacks

Symptom: Attack from many different IPs, rate limiting per-IP not effective.

Diagnosis: 1. Review security logs for attack pattern 2. Note geographic distribution 3. Check user agent patterns 4. Identify attack type (login, API, etc.)

Solution: – Enable geographic blocking for attack source countries – Enable bot protection if automated – Lower rate limits aggressively – Consider temporary site-wide restrictions

Best Practices

Start Conservative: Begin with lower limits, increase if needed. Easier to increase than decrease.

Monitor Actively: Watch logs for first 48 hours after enabling rate limiting.

Document Changes: Record limits, rationale, and any adjustments made.

Test Thoroughly: Verify legitimate workflows still function correctly.

Use Appropriate Response: 403 for visibility, Drop for aggressive blocking.

Layer Protections: Combine rate limiting with geographic blocking, bot protection, and IP whitelisting.

Review Regularly: Quarterly review of rate limits and effectiveness.

Plan for Events: Increase limits temporarily during marketing campaigns or known high-traffic periods.

Rate limiting is effective against automated abuse while minimizing impact on legitimate users when properly configured and monitored.