Rate Limiting for Proxy API

Overview

The frontend proxy API (/api/proxy) now includes rate limiting to prevent abuse and protect the backend from being flooded with requests. The rate limiting is implemented using an in-memory store with configurable limits.

Features

1. General Rate Limiting

  • Default: 60 requests per minute per IP address
  • Applied to all requests through the proxy
  • Returns 429 status code when limit exceeded
  • Includes Retry-After header indicating when to retry

2. Failure Rate Limiting

  • Default: 10 failed requests per 5 minutes per IP address
  • Only counts requests that result in errors
  • Prevents repeated abuse attempts
  • Helps identify and block malicious actors

3. Rate Limit Headers

All responses include rate limit information:

  • X-RateLimit-Remaining: Number of requests remaining in the current window
  • X-Request-ID: Unique request identifier for tracking
  • X-FailureRateLimit-Remaining: Remaining failure attempts (on error responses)

Configuration

The rate limiters can be configured in /src/lib/rate-limiter.ts:

// Default rate limiter (60 req/min)
export const createDefaultRateLimiter = () => new RateLimiter({
  windowMs: 60 * 1000,  // 1 minute
  maxRequests: 60,      // 60 requests per minute
  message: 'Too many requests, please try again later'
});

// Failure rate limiter (10 failures/5min)
export const createFailureRateLimiter = () => new RateLimiter({
  windowMs: 5 * 60 * 1000,  // 5 minutes
  maxRequests: 10,          // 10 failures per 5 minutes
  skipSuccessfulRequests: true,
  message: 'Too many failed requests, please try again later'
});

Client Handling

When implementing client-side code that calls the proxy API, handle rate limit responses:

const response = await fetch('/api/proxy', {
  method: 'POST',
  body: JSON.stringify({ endpoint: '/vac/assistant/123', ... })
});

if (response.status === 429) {
  const retryAfter = response.headers.get('Retry-After');
  const data = await response.json();
  
  // Show error to user
  console.error(`Rate limited: ${data.error}. Retry after ${retryAfter} seconds`);
  
  // Optionally implement exponential backoff
  setTimeout(() => {
    // Retry the request
  }, parseInt(retryAfter) * 1000);
}

IP Address Detection

The rate limiter uses the following order to determine client IP:

  1. X-Forwarded-For header (first IP if multiple)
  2. X-Real-IP header
  3. Falls back to ‘unknown’ if no IP headers present

Custom Rate Limiters

You can create custom rate limiters for specific use cases:

// Strict rate limiter for sensitive endpoints
const strictLimiter = new RateLimiter({
  windowMs: 60 * 1000,
  maxRequests: 10,
  keyGenerator: (req) => {
    // Custom key based on user ID + IP
    const userId = req.headers.get('X-User-ID');
    const ip = req.headers.get('X-Forwarded-For');
    return `${userId}:${ip}`;
  }
});

// Burst rate limiter (allows short bursts)
const burstLimiter = new RateLimiter({
  windowMs: 1000,      // 1 second
  maxRequests: 10,     // 10 requests per second
});

Memory Management

  • Rate limit records are stored in memory
  • Expired records are automatically cleaned up every minute
  • Memory usage scales with number of unique IPs
  • For production deployments with high traffic, consider using Redis-based rate limiting

Testing

Run the rate limiter tests:

npm run test:run src/lib/__tests__/rate-limiter.test.ts

The tests cover:

  • Basic rate limiting functionality
  • Time window resets
  • IP-based tracking
  • Selective counting (failures only)
  • Custom key generation
  • Memory cleanup

Monitoring

Monitor rate limit effectiveness by tracking:

  • 429 response rates
  • X-RateLimit-Remaining values in successful responses
  • Request patterns from specific IPs
  • Failed request patterns

Future Enhancements

Consider these improvements for production:

  1. Redis-based storage for distributed deployments
  2. User-based rate limiting in addition to IP-based
  3. Dynamic rate limits based on user tier/subscription
  4. Webhook notifications for repeated rate limit violations
  5. Allowlist/blocklist for specific IPs or users