Post

Rate Limiting

Rate Limiting

What is Rate Limiting?

Rate limiting is a technique used to control the number of requests a user, client, or system can make to a resource—such as an API, website, or service—within a specified period of time. By enforcing these limits, you can prevent abuse, protect your infrastructure from overload, and ensure a fair experience for all users. Rate limiting is a fundamental part of API design, web security, and scalable system architecture.

Why is Rate Limiting Important?

  • Prevents Abuse & Attacks: Stops malicious actors or bots from overwhelming your service with excessive requests (e.g., brute-force, scraping, or denial-of-service attacks).
  • Protects Resources: Shields your backend, databases, and third-party services from being overloaded, which can lead to downtime or increased costs.
  • Ensures Fairness: Guarantees that all users have equitable access to your service, preventing a single user from monopolizing resources.
  • Improves Reliability: Helps maintain consistent performance and availability, even under heavy load or unexpected traffic spikes.

Common Algorithms

  • Fixed Window: Simple counter per window (e.g., 100 requests/minute)
  • Sliding Window: Tracks requests in a rolling window for smoother limiting
  • Token Bucket: Allows bursts; tokens refill at a set rate
  • Leaky Bucket: Processes requests at a steady rate; excess is dropped or queued

Rate Limiting Examples: Flask (limits) vs Django


# Flask + limits (with Redis)
from flask import Flask, request, jsonify
from limits import parse
from limits.storage import RedisStorage
from limits.strategies import FixedWindowRateLimiter

app = Flask(__name__)
storage = RedisStorage("redis://localhost:6379")
limiter = FixedWindowRateLimiter(storage)
rate_limit = parse("5/minute")  # 5 requests per minute

@app.route('/api')
def my_api():
    client_ip = request.remote_addr
    if not limiter.hit(rate_limit, client_ip):
        return jsonify({'error': 'Rate limit exceeded.'}), 429
    return jsonify({'message': 'Request successful!'})

if __name__ == '__main__':
    app.run(debug=True)
    

Best Practices

  • Return HTTP 429 for rate limit violations
  • Inform users of their limit status (headers or body)
  • Use Redis or similar for distributed setups
  • Use libraries like Flask-Limiter, limits, or django-ratelimit

Summary Table

MethodAllows BurstsSmoothMemory UsageComplexityUse Case
Fixed WindowNoNoLowLowSimple APIs
Sliding Window LogNoYesHighMediumHigh-accuracy APIs
Sliding Window CounterNoYesMediumMediumSmoother limits
Token BucketYesYesLowMediumMost APIs
Leaky BucketNoYesLowMediumSteady flow needed
Concurrent LimitingN/AN/ALowLowResource protection
Dynamic/AdaptiveVariesVariesVariesHighLarge-scale platforms

References:

This post is licensed under CC BY 4.0 by the author.