Working with APIs

Rate Limiting

Protect your APIs and simulate real-world usage limits

What is Rate Limiting?

Rate limiting is a technique to control how many requests a client can make to your API within a specific time window. It prevents abuse, ensures fair usage, and protects server resources.

Why Use Rate Limiting?

  • Prevent Abuse: Stop malicious users from overwhelming your API
  • Fair Usage: Ensure all users get equal access to resources
  • Cost Control: Limit expensive operations and database queries
  • Real-World Testing: Simulate production API behavior in development
  • Performance: Maintain consistent response times under load

How It Works

Mock API Builder uses a sliding window rate limiting algorithm:

1

Request Arrives

Client makes a request to your API endpoint

2

Check Limit

System checks how many requests were made in the last time window

3

Allow or Block

If under limit: Request proceeds normally

If over limit: Return 429 Too Many Requests error

4

Reset Window

Counter resets after the time window expires

Rate Limit Configuration

Request Limit

Maximum number of requests allowed in the time window

Default: 100 requests

Range: 10 - 10,000 requests

Recommended:

  • • Development: 100-1,000 requests
  • • Testing: 10-50 requests (to test limits)
  • • Production simulation: 1,000-5,000 requests
Time Window

Duration for counting requests (sliding window)

Default: 15 minutes (900 seconds)

Options:

  • • 1 minute (60s) - Strict limits
  • • 15 minutes (900s) - Standard
  • • 1 hour (3600s) - Lenient
  • • Custom duration in seconds
Scope

How rate limits are applied

Per IP Address (Default)

Each client IP gets its own limit counter

Global (Coming Soon)

Total requests from all clients combined

Rate Limit Response

When a client exceeds the rate limit, they receive a 429 status code with helpful headers:

429
Too Many Requests Response

Response Headers:

X-RateLimit-Limit: 100X-RateLimit-Remaining: 0X-RateLimit-Reset: 1704024000Retry-After: 300

Response Body:

{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Try again in 5 minutes.",
  "retryAfter": 300
}

Response Headers Explained

X-RateLimit-Limit

Maximum number of requests allowed in the time window

X-RateLimit-Limit: 100
X-RateLimit-Remaining

Number of requests remaining before hitting the limit

X-RateLimit-Remaining: 42
X-RateLimit-Reset

Unix timestamp when the rate limit resets

X-RateLimit-Reset: 1704024000

Convert to human-readable: new Date(1704024000 * 1000)

Retry-After

Number of seconds to wait before retrying (only when rate limited)

Retry-After: 300

Handling Rate Limits in Code

JavaScript/TypeScript Example
async function fetchWithRateLimit(url: string) {
  const response = await fetch(url);
  
  // Check rate limit headers
  const limit = response.headers.get('X-RateLimit-Limit');
  const remaining = response.headers.get('X-RateLimit-Remaining');
  const reset = response.headers.get('X-RateLimit-Reset');
  
  console.log(`Rate limit: ${remaining}/${limit}`);
  
  // Handle rate limit exceeded
  if (response.status === 429) {
    const retryAfter = response.headers.get('Retry-After');
    console.warn(`Rate limited! Retry after ${retryAfter}s`);
    
    // Wait and retry
    await new Promise(resolve => 
      setTimeout(resolve, Number(retryAfter) * 1000)
    );
    return fetchWithRateLimit(url); // Retry
  }
  
  return response.json();
}
React Hook Example
function useAPIWithRateLimit(endpoint: string) {
  const [data, setData] = useState(null);
  const [rateLimit, setRateLimit] = useState({
    limit: 0,
    remaining: 0,
    reset: 0
  });
  
  useEffect(() => {
    async function fetchData() {
      const res = await fetch(endpoint);
      
      // Track rate limit info
      setRateLimit({
        limit: Number(res.headers.get('X-RateLimit-Limit')),
        remaining: Number(res.headers.get('X-RateLimit-Remaining')),
        reset: Number(res.headers.get('X-RateLimit-Reset'))
      });
      
      if (res.status === 429) {
        const retryAfter = res.headers.get('Retry-After');
        // Show user message
        console.warn(`Please wait ${retryAfter}s`);
        return;
      }
      
      setData(await res.json());
    }
    
    fetchData();
  }, [endpoint]);
  
  return { data, rateLimit };
}

Testing Rate Limits

Quick Test Script

Use this script to quickly test your rate limits:

// Send 150 requests to test 100 request limit
async function testRateLimit() {
  const endpoint = 'http://localhost:3000/api/users';
  
  for (let i = 1; i <= 150; i++) {
    const response = await fetch(endpoint);
    const remaining = response.headers.get('X-RateLimit-Remaining');
    
    console.log(`Request #${i}: ${response.status} - ${remaining} remaining`);
    
    if (response.status === 429) {
      console.error('Rate limit hit at request #' + i);
      break;
    }
    
    // Small delay to see results clearly
    await new Promise(r => setTimeout(r, 50));
  }
}

testRateLimit();

Common Use Cases

Strict Limits (Authentication)

Prevent brute force attacks

Limit: 10 requests

Window: 1 minute

Standard API (Read Operations)

Normal usage protection

Limit: 100 requests

Window: 15 minutes

Heavy Operations (Search, Export)

Protect expensive operations

Limit: 20 requests

Window: 1 hour

Development/Testing

Generous limits for development

Limit: 1,000 requests

Window: 15 minutes

Best Practices

✓ Always Check Headers

Monitor X-RateLimit-Remaining to know when you're approaching the limit. Display this to users in dev tools.

✓ Implement Retry Logic

Use the Retry-After header to automatically retry requests after waiting the specified time.

✓ Cache Responses

Store frequently accessed data locally to reduce API calls and stay within rate limits.

✓ Show User Feedback

Display clear messages when users hit rate limits: "You've made too many requests. Please wait 5 minutes."

✓ Test Edge Cases

Intentionally exceed rate limits during testing to ensure your error handling works correctly.