Skip to main content

A flexible and efficient rate limiting library for Django applications

Project description

Django Smart Ratelimit

CI PyPI version PyPI status Python versions Django versions Downloads License GitHub Discussions

A comprehensive rate limiting library for Django applications with multiple algorithms, backends, and flexible configuration options.

Why Rate Limiting Matters

Rate limiting helps protect your Django applications from:

  • Resource exhaustion from excessive requests
  • Brute force attacks on authentication endpoints
  • API abuse and scraping attempts
  • Unintentional traffic spikes that can overwhelm your server

Why Choose Django Smart Ratelimit?

Comparison with Other Packages

Feature django-smart-ratelimit django-ratelimit Other Packages
Maintenance Status โœ… Actively maintained ๐Ÿ”„ Minimal maintenance (last release Jul 2023) ๐Ÿ”„ Varies
Multiple Algorithms โœ… Token bucket, sliding window, fixed window โŒ Fixed window only โŒ Usually basic
Backend Flexibility โœ… Redis, Database, Memory, Multi-backend โŒ Django cache framework only โŒ Limited options
Circuit Breaker Protection โœ… Automatic failure recovery โŒ No โŒ Rarely available
Atomic Operations โœ… Redis Lua scripts prevent race conditions โŒ Race condition prone โŒ Usually not atomic
Automatic Failover โœ… Graceful degradation between backends โŒ No โŒ Single point of failure
Type Safety โœ… Full mypy compatibility โŒ No type hints โŒ Usually untyped
Decorator Syntax โœ… @rate_limit() โœ… @ratelimit() ๐Ÿ”„ Varies
Monitoring Tools โœ… Health checks, cleanup commands โŒ No โŒ Usually manual
Standard Headers โœ… X-RateLimit-* headers โŒ No headers โŒ Inconsistent
Concurrency Safety โœ… Race condition free โŒ Race conditions possible โŒ Usually problematic

Key Advantages

๐Ÿš€ Modern Architecture: Built from the ground up with modern Django best practices, type safety, and comprehensive testing.

๐Ÿ”ง Enterprise-Ready: Multiple algorithms and backends allow you to choose the right solution for your specific use case - from simple fixed windows to sophisticated token buckets with burst handling.

๐Ÿ›ก๏ธ Reliability: Circuit breaker protection and automatic failover ensure your rate limiting doesn't become a single point of failure.

๐Ÿ“Š Observability: Built-in monitoring, health checks, and standard HTTP headers provide visibility into rate limiting behavior.

๐Ÿ”„ Migration Path: Easy migration from django-ratelimit with similar decorator syntax but enhanced functionality.

Library Features

  • Multiple algorithms: Token bucket, sliding window, and fixed window
  • Backend flexibility: Redis, Database, Memory, and Multi-Backend support
  • Circuit breaker protection: Automatic failure detection and recovery for backends
  • Atomic operations: Redis Lua scripts prevent race conditions
  • Automatic failover: Graceful degradation between backends
  • Type safety: Full mypy compatibility with strict type checking
  • Framework integration: Native Django and Django REST Framework support
  • Monitoring tools: Health checks and cleanup management commands
  • Standard headers: X-RateLimit-* headers for client information

Quick Start

Installation

pip install django-smart-ratelimit[redis]

Basic Usage

from django_smart_ratelimit import rate_limit

# IP-based rate limiting
@rate_limit(key='ip', rate='100/h')
def api_endpoint(request):
    return JsonResponse({'data': 'protected'})

# User-based rate limiting
@rate_limit(key='user', rate='50/h')
def user_dashboard(request):
    return JsonResponse({'user_data': '...'})

Authentication Protection

@rate_limit(key='ip', rate='5/m', block=True)
def login_view(request):
    return authenticate_user(request)

Django REST Framework

from rest_framework import viewsets
from django_smart_ratelimit import rate_limit

class APIViewSet(viewsets.ViewSet):
    @rate_limit(key='ip', rate='100/h')
    def list(self, request):
        return Response({'data': 'list'})

Middleware Configuration

# settings.py
MIDDLEWARE = ['django_smart_ratelimit.middleware.RateLimitMiddleware']
RATELIMIT_MIDDLEWARE = {
    'DEFAULT_RATE': '1000/h',
    'RATE_LIMITS': {
        '/api/auth/': '10/m',
        '/api/': '500/h',
    }
}

Migration from django-ratelimit

Migrating from django-ratelimit is straightforward with minimal code changes:

Basic Decorator Migration

# OLD: django-ratelimit
from django_ratelimit.decorators import ratelimit

@ratelimit(key='ip', rate='10/m', block=True)
def my_view(request):
    return HttpResponse('Hello')

# NEW: django-smart-ratelimit
from django_smart_ratelimit import rate_limit

@rate_limit(key='ip', rate='10/m', block=True)
def my_view(request):
    return HttpResponse('Hello')

Enhanced Features Available

# NEW: Add algorithm choice
@rate_limit(key='ip', rate='10/m', algorithm='token_bucket')

# NEW: Add backend failover
@rate_limit(key='ip', rate='10/m', backend='redis')

# NEW: Add skip conditions
@rate_limit(key='ip', rate='10/m', skip_if=lambda req: req.user.is_staff)

Key Migration Benefits

  • Drop-in replacement: Same decorator syntax (ratelimit vs. rate_limit)
  • Enhanced reliability: Circuit breaker protection
  • Better performance: Atomic Redis operations
  • More flexibility: Multiple algorithms and backends
  • Active maintenance: Regular updates and bug fixes

Algorithm Comparison

Algorithm Characteristics Best For
token_bucket Allows traffic bursts APIs with variable load
sliding_window Smooth request distribution Consistent traffic control
fixed_window Simple, predictable behavior Basic rate limiting needs

Token Bucket Algorithm

The token bucket algorithm allows for burst traffic handling:

@rate_limit(
    key='user',
    rate='100/h',  # Base rate
    algorithm='token_bucket',
    algorithm_config={
        'bucket_size': 200,  # Allow bursts up to 200 requests
        'refill_rate': 2.0,  # Refill tokens at 2 per second
    }
)
def api_with_bursts(request):
    return JsonResponse({'data': 'handled'})

Common use cases:

  • Mobile app synchronization after offline periods
  • Batch file processing
  • API retry mechanisms

Backend Configuration

Redis (Recommended)

RATELIMIT_BACKEND = 'redis'
RATELIMIT_REDIS = {
    'host': 'localhost',
    'port': 6379,
    'db': 0,
}

Database

RATELIMIT_BACKEND = 'database'
# Uses your default Django database

Upgrade note: Run python manage.py migrate after upgrading to ensure the new RateLimitCounter.data column exists. The database backend now stores serialized token-bucket state in this field so token counts persist across requests.

Multi-Backend with Failover

RATELIMIT_BACKENDS = [
    {
        'name': 'primary_redis',
        'backend': 'redis',
        'config': {'host': 'redis-primary.example.com'}
    },
    {
        'name': 'fallback_db',
        'backend': 'database',
        'config': {}
    }
]

Response Headers

The library adds standard rate limit headers to responses:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1642678800
Retry-After: 200

Monitoring and Management

Health Checks

# Check backend health
python manage.py ratelimit_health

# Detailed status
python manage.py ratelimit_health --verbose

Cleanup (Database Backend)

# Clean expired entries
python manage.py cleanup_ratelimit

# Preview cleanup
python manage.py cleanup_ratelimit --dry-run

Library Features

  • Multiple algorithms: Token bucket, sliding window, and fixed window
  • Backend flexibility: Redis, Database, Memory, and Multi-Backend support
  • Atomic operations: Redis Lua scripts prevent race conditions
  • Automatic failover: Graceful degradation between backends
  • Type safety: Full mypy compatibility with strict type checking
  • Framework integration: Native Django and Django REST Framework support

Examples

The library includes comprehensive examples for various use cases:

Configuration Options

Decorator Parameters

@rate_limit(
    key='user',                    # Key function or string
    rate='100/h',                  # Rate limit (requests/period)
    algorithm='token_bucket',      # Algorithm choice
    algorithm_config={},           # Algorithm-specific config
    backend='redis',               # Backend override
    block=True,                    # Block vs. continue on limit
    skip_if=lambda req: req.user.is_staff,  # Skip condition
)

Testing

# Run tests
python -m pytest

# Run with coverage
python -m pytest --cov=django_smart_ratelimit

Decorator Examples

from django_smart_ratelimit import rate_limit

# Basic IP-based limiting
@rate_limit(key='ip', rate='10/m')
def public_api(request):
    return JsonResponse({'message': 'Hello World'})

# User-based limiting (automatically falls back to IP for anonymous users)
@rate_limit(key='user', rate='100/h')
def user_dashboard(request):
    return JsonResponse({'user_data': '...'})

# Custom key function for more control
@rate_limit(key=lambda req: f"user:{req.user.id}" if req.user.is_authenticated else f"ip:{req.META.get('REMOTE_ADDR')}", rate='50/h')
def flexible_api(request):
    return JsonResponse({'data': '...'})

# Block when limit exceeded (default is to continue)
@rate_limit(key='ip', rate='5/m', block=True)
def strict_api(request):
    return JsonResponse({'sensitive': 'data'})

# Skip rate limiting for staff users
@rate_limit(key='ip', rate='10/m', skip_if=lambda req: req.user.is_staff)
def staff_friendly_api(request):
    return JsonResponse({'data': 'staff can access unlimited'})

# Use sliding window algorithm
@rate_limit(key='user', rate='100/h', algorithm='sliding_window')
def smooth_api(request):
    return JsonResponse({'algorithm': 'sliding_window'})

# Use fixed window algorithm
@rate_limit(key='ip', rate='20/m', algorithm='fixed_window')
def burst_api(request):
    return JsonResponse({'algorithm': 'fixed_window'})

# Use token bucket algorithm (NEW!)
@rate_limit(
    key='api_key',
    rate='100/m',  # Base rate: 100 requests per minute
    algorithm='token_bucket',
    algorithm_config={
        'bucket_size': 200,  # Allow bursts up to 200 requests
        'refill_rate': 2.0,  # Refill at 2 tokens per second
    }
)
def api_with_bursts(request):
    return JsonResponse({'algorithm': 'token_bucket', 'burst_allowed': True})

Circuit Breaker Protection

Automatic failure detection and recovery for backend operations to ensure system reliability:

Configuration

# settings.py
RATELIMIT_CIRCUIT_BREAKER = {
    'failure_threshold': 5,        # Open circuit after 5 failures
    'recovery_timeout': 60,        # Wait 60 seconds before testing recovery
    'reset_timeout': 300,          # Reset after 5 minutes of success
    'half_open_max_calls': 1,      # Test with 1 call in half-open state
}

Backend-Specific Circuit Breakers

from django_smart_ratelimit.backends import MemoryBackend

# Enable circuit breaker (default: enabled)
backend = MemoryBackend(enable_circuit_breaker=True)

# Custom configuration
custom_config = {'failure_threshold': 3, 'recovery_timeout': 30}
backend = MemoryBackend(
    enable_circuit_breaker=True,
    circuit_breaker_config=custom_config
)

# Check circuit breaker status
status = backend.get_backend_health_status()
print(f"Circuit breaker enabled: {status['circuit_breaker_enabled']}")
print(f"Current state: {status['circuit_breaker']['state']}")

Circuit Breaker States

  • ๐ŸŸข CLOSED: Normal operation, requests pass through
  • ๐Ÿ”ด OPEN: Too many failures, requests fail fast (no backend calls)
  • ๐ŸŸก HALF_OPEN: Testing recovery with limited requests

Community & Support

๐Ÿ’– Support the Project

If you find this project helpful and want to support its development, you can make a donation to help maintain and improve this open-source library:

Cryptocurrency Donations

  • USDT (Ethereum Network): 0xBD90e5df7389295AE6fbaB5FEf6817f22A8123eF
  • Solana (SOL): WzQHS7hzBcznkYoR7TkMH1DRo3WLYQdWCNBuy6ZfY3h
  • Ripple (XRP): rE8CM2sv4gBEDhek2Ajm2vMmqMXdPV34jC

Your support helps maintain and improve this project for the Django community! ๐Ÿ™

License

This project is licensed under the MIT License - see the LICENSE file for details.


๐Ÿ“š Documentation โ€ข ๐Ÿ’ก Examples โ€ข ๐Ÿค Contributing โ€ข ๐Ÿ’ฌ Discussions โ€ข ๐Ÿค– AI Usage

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_smart_ratelimit-0.8.11.tar.gz (163.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_smart_ratelimit-0.8.11-py3-none-any.whl (89.2 kB view details)

Uploaded Python 3

File details

Details for the file django_smart_ratelimit-0.8.11.tar.gz.

File metadata

  • Download URL: django_smart_ratelimit-0.8.11.tar.gz
  • Upload date:
  • Size: 163.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for django_smart_ratelimit-0.8.11.tar.gz
Algorithm Hash digest
SHA256 439d97df959b6e9cc2afbc983ddbe5f8e6b24707298dc66f6bf93dc9c5f93fa2
MD5 72c7eccfe62b48ecf1f358403c16e4d6
BLAKE2b-256 03f910b260ba3a02508eb47787e8413cf38d0e0b0b211c8a47bfd6a8be871502

See more details on using hashes here.

File details

Details for the file django_smart_ratelimit-0.8.11-py3-none-any.whl.

File metadata

File hashes

Hashes for django_smart_ratelimit-0.8.11-py3-none-any.whl
Algorithm Hash digest
SHA256 5be0de0dc7b68e2e7883ac39d0005b9de97f33eed8fd6016b95a19974f57fe13
MD5 3f7058d601c439b8e4cf9657769b6347
BLAKE2b-256 26560f5024cf3dad1bd631ccfcdb47b95302ba3931ee866366252974d19b0afc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page