Isaac.

API Rate Limiting

Implement rate limiting to protect APIs from abuse and overload.

By EMEPublished: February 20, 2025
apirate limitingthrottlingprotectionperformance

A Simple Analogy

Rate limiting is like a bouncer at a nightclub. They control how many people enter per minute to prevent overcrowding. Without limits, the club becomes unusable for everyone. APIs need bouncers too.


What Is Rate Limiting?

Rate limiting controls how many requests a client can make to an API in a time period. It prevents abuse, ensures fair usage, and protects server resources.


Why Implement Rate Limiting?

  • Prevent abuse: Stop malicious users from overwhelming servers
  • Fair usage: Ensure all users get access
  • Stability: Prevent cascading failures
  • Predictability: Smooth traffic patterns
  • Revenue: Different tiers get different limits

Rate Limiting Strategies

| Strategy | How It Works | Use Case | |----------|-------------|----------| | Token Bucket | Tokens replenish over time | Bursts allowed | | Sliding Window | Count requests in time window | Strict limits | | Leaky Bucket | Drain at constant rate | Smooth traffic | | Fixed Window | Reset counter at intervals | Simple, predictable |


.NET Implementation

// Using AspNetCoreRateLimit package

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMemoryCache();
builder.Services.AddInMemoryRateLimiting();

var ipRateLimitPolicies = new List<IpRateLimitPolicy>
{
    new IpRateLimitPolicy
    {
        IpPrefix = "*",  // All IPs
        Rules = new List<RateLimitRule>
        {
            new RateLimitRule
            {
                Endpoint = "*",  // All endpoints
                Limit = 100,      // 100 requests
                Period = "1m"     // per 1 minute
            }
        }
    }
};

builder.Services.Configure<IpRateLimitOptions>(options =>
{
    options.IpWhitelist = new List<string> { "127.0.0.1" };
    options.Policies = ipRateLimitPolicies;
});

var app = builder.Build();
app.UseIpRateLimiting();

Custom Rate Limiting Middleware

public class RateLimitMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IMemoryCache _cache;
    private const int MaxRequests = 100;
    private const int WindowSeconds = 60;
    
    public RateLimitMiddleware(RequestDelegate next, IMemoryCache cache)
    {
        _next = next;
        _cache = cache;
    }
    
    public async Task InvokeAsync(HttpContext context)
    {
        var clientId = context.Connection.RemoteIpAddress?.ToString();
        var cacheKey = $"ratelimit_{clientId}";
        
        if (!_cache.TryGetValue(cacheKey, out int requestCount))
        {
            requestCount = 0;
        }
        
        if (requestCount >= MaxRequests)
        {
            context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
            await context.Response.WriteAsync("Rate limit exceeded");
            return;
        }
        
        _cache.Set(cacheKey, requestCount + 1, TimeSpan.FromSeconds(WindowSeconds));
        
        await _next(context);
    }
}

// Register middleware
app.UseMiddleware<RateLimitMiddleware>();

API Response Headers

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1640000000

HTTP 429 Too Many Requests
Retry-After: 30

Practical Example

[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
    [HttpGet]
    public IActionResult GetData()
    {
        var clientIp = HttpContext.Connection.RemoteIpAddress?.ToString();
        
        // Check rate limit
        // If exceeded, return 429
        
        return Ok(new { message = "Data" });
    }
}

Best Practices

  1. Include headers: Tell clients their limit status
  2. Graceful degradation: Return useful error messages
  3. Whitelist: Exclude internal services
  4. Tiered limits: Different limits for different API tiers
  5. Monitor: Track rate limit violations

Related Concepts to Explore

  • Distributed rate limiting (Redis)
  • Per-user vs. per-IP limiting
  • Adaptive rate limiting
  • API quota management
  • DDoS protection

Summary

Rate limiting protects APIs by controlling request volume. Implement appropriate limits to prevent abuse, ensure fair usage, and maintain service stability.