web
Implementing Rate Limiting
Protect endpoints from abuse with rate limiting strategies.
By Emem IsaacJune 24, 20232 min read
#rate limiting#api protection#middleware#throttling
Share:
A Simple Analogy
Rate limiting is like a speed limit on highways. It prevents abuse by restricting how fast (many requests) can happen.
Why Rate Limiting?
- Abuse prevention: Block malicious clients
- Resource protection: Don't overload servers
- Fair access: Prevent monopolization
- Cost control: Limit API usage costs
- DoS protection: Mitigate attacks
Per-IP Rate Limiting
public class IpRateLimitMiddleware
{
private readonly RequestDelegate _next;
private readonly ConcurrentDictionary<string, RateLimit> _limits;
public IpRateLimitMiddleware(RequestDelegate next)
{
_next = next;
_limits = new ConcurrentDictionary<string, RateLimit>();
}
public async Task InvokeAsync(HttpContext context)
{
var ip = context.Connection.RemoteIpAddress.ToString();
var limit = _limits.GetOrAdd(ip, _ => new RateLimit(100, TimeSpan.FromMinutes(1)));
if (!limit.IsAllowed())
{
context.Response.StatusCode = 429;
context.Response.Headers.Add("Retry-After", "60");
await context.Response.WriteAsync("Rate limit exceeded");
return;
}
await _next(context);
}
public class RateLimit
{
private int _remaining;
private DateTime _resetTime;
public RateLimit(int limit, TimeSpan window)
{
_remaining = limit;
_resetTime = DateTime.UtcNow.Add(window);
}
public bool IsAllowed()
{
if (DateTime.UtcNow >= _resetTime)
{
_remaining = 100;
_resetTime = DateTime.UtcNow.AddMinutes(1);
}
if (_remaining > 0)
{
_remaining--;
return true;
}
return false;
}
}
}
Header-Based Response
context.Response.Headers.Add("X-RateLimit-Limit", "100");
context.Response.Headers.Add("X-RateLimit-Remaining", "45");
context.Response.Headers.Add("X-RateLimit-Reset", "1645000000");
// Or
context.Response.Headers.Add("Retry-After", "60"); // seconds to wait
Sliding Window
public class SlidingWindowCounter
{
private readonly Queue<DateTime> _requests = new();
private readonly int _limit;
private readonly TimeSpan _window;
public SlidingWindowCounter(int limit, TimeSpan window)
{
_limit = limit;
_window = window;
}
public bool IsAllowed()
{
var now = DateTime.UtcNow;
var cutoff = now.Subtract(_window);
// Remove old requests
while (_requests.Count > 0 && _requests.Peek() < cutoff)
{
_requests.Dequeue();
}
if (_requests.Count < _limit)
{
_requests.Enqueue(now);
return true;
}
return false;
}
}
Endpoint-Specific Limits
[RateLimit(limit: 100, window: 60)] // 100 requests per 60 seconds
[HttpGet("products")]
public async Task<IActionResult> GetProducts()
{
return Ok(await _service.GetProductsAsync());
}
[RateLimit(limit: 10, window: 60)] // Stricter for writes
[HttpPost("products")]
public async Task<IActionResult> CreateProduct(CreateProductRequest req)
{
var product = await _service.CreateAsync(req);
return CreatedAtAction(nameof(GetProducts), new { id = product.Id });
}
Best Practices
- Be generous: Don't limit legitimate users
- Inform clients: Use headers clearly
- Transparent: Document limits in API docs
- Graceful degradation: Queue instead of reject
- Monitor: Track limit violations
Related Concepts
- Quota management
- Throttling
- Traffic shaping
- DDoS protection
Summary
Implement rate limiting to protect endpoints from abuse. Use per-IP tracking, sliding windows, and clear response headers.
Share:
Related Articles
web
API Rate Limiting Implementation
Implement rate limiting to protect APIs from abuse.
Read More securityRate Limiting and Throttling
Protect APIs with rate limiting and throttling strategies.
Read More webAngular Component Communication
Implement patterns for component communication in Angular.
Read More