Skip to main content

Production-ready rate limiting and DDoS protection for Python web frameworks

Project description

drogue

GitHub stars Python 3.10+ License: MIT Tests PyPI version PyPI downloads Supported frameworks

Rate limiting and DDoS protection for Python web applications. Clean APIs, WebSocket support, and built-in defense layers.

Read the documentation


What problem does drogue solve?

Web applications need rate limiting to prevent abuse, but existing solutions have gaps:

  1. Signature pollution -- Most rate limiters force request: Request into every function signature, coupling your business logic to the rate limiter.

  2. No WebSocket protection -- Real-time applications using WebSockets have no built-in rate limiting.

  3. No DDoS detection -- Simple counters catch over-use, but cannot detect distributed attacks where each client stays below the limit.

  4. No trust differentiation -- Every request goes through the same evaluation path, even for verified users.

drogue addresses all four. It rate-limits by identity (IP, user, header) without touching your function signatures, detects anomalous traffic patterns, and fast-tracks trusted clients.


Who is drogue for?

  • API developers who need rate limiting without framework lock-in
  • Teams running FastAPI, Django, or Flask who want a single solution across all three
  • Platforms facing DDoS or abuse that need more than simple request counting
  • Applications with WebSocket connections that need real-time protection

How it works

from fastapi import FastAPI
from drogue.adapters.fastapi import DrogueLimiter

app = FastAPI()
limiter = DrogueLimiter(app, default_limits=["100/minute"])

@app.get("/api/data")
@limiter.limit("10/minute")
async def get_data():
    return {"data": "value"}

No request: Request parameter. Rate limit headers are injected automatically. The same pattern works for Flask and Django.

Request flow:

  1. Client sends a request
  2. drogue extracts the client key (IP, user ID, or custom header)
  3. Rules are matched against the route
  4. The algorithm evaluates the request (Token Bucket, Sliding Window, or Fixed Window)
  5. Protection layers run (DDoS check, trust state, probe detection)
  6. Response is returned with rate limit headers

Features

Category What you get
Rate Limiting Token Bucket, Sliding Window, Fixed Window, cost-aware limits, blocking mode, burst control
Identity IP-based, user-based, header-based, composite extractors, anti-spoof X-Forwarded-For
Frameworks FastAPI (ASGI), Flask (decorator), Django (middleware + decorator), Django REST Framework (throttle)
DDoS Detection Z-score anomaly detection, streaming Sentinel Model, probe pattern detection
Auto-Ban Progressive ban with doubling duration (5m to 160m), configurable thresholds
Trust System State machine (Unknown/Normal/Trusted/Distrusted/Banned), 9x throughput for verified users
Circuit Breaker Closed/Open/HalfOpen states, automatic recovery
Adaptive Limits CPU and memory-based scaling, reduces limits under system load
Defense Randomization Per-session variance, honeypot paths, anti-fingerprinting
CIDR Filtering Allow/block lists from config or files, IPv4 and IPv6
Probabilistic Storage Count-Min Sketch (10MB for 1M keys), Bloom Filter, Cuckoo Filter, HyperLogLog
Observability Prometheus metrics, OpenTelemetry tracing, structured JSON logging
Shadow Mode Test rules without enforcing, collect metrics before go-live

Performance

Metric drogue Notes
Token Bucket ~1.4us median latency per acquire
Sliding Window ~1.6us median latency per acquire
Fixed Window ~1.1us median latency per acquire
Throughput 700K+ req/s single worker, in-memory storage
Memory per key ~150 bytes in-process storage

Measured on Intel Core Ultra 5 225F, Python 3.13, asyncio single-worker, in-memory storage, 100K iterations.


Install

pip install drogue

# With framework extras
pip install drogue[fastapi]   # FastAPI + Starlette
pip install drogue[django]    # Django
pip install drogue[flask]     # Flask
pip install drogue[drf]       # Django REST Framework
pip install drogue[redis]     # Redis backend
pip install drogue[all]       # Everything

Quick Start

FastAPI:

from fastapi import FastAPI
from drogue.adapters.fastapi import DrogueLimiter

app = FastAPI()
limiter = DrogueLimiter(app, default_limits=["100/minute"])

@app.get("/api/data")
@limiter.limit("10/minute")
async def get_data():
    return {"data": "value"}

Flask:

from flask import Flask
from drogue.adapters.flask import DrogueLimiter

app = Flask(__name__)
limiter = DrogueLimiter(app, default_limits=["100/minute"])

@app.route("/api/data")
@limiter.limit("10/minute")
def get_data():
    return {"data": "value"}

Django:

# settings.py
MIDDLEWARE = [
    "drogue.adapters.django.DrogueMiddleware",
]

# views.py
from drogue.adapters.django import DrogueRateLimiter
from django.http import JsonResponse

limiter = DrogueRateLimiter()

@limiter.limit("10/minute")
def get_data(request):
    return JsonResponse({"data": "value"})

Migration from slowapi

# Before (slowapi)
from slowapi import Limiter
from slowapi.util import get_remote_address
from starlette.requests import Request

limiter = Limiter(key_func=get_remote_address)

@app.get("/api/data")
@limiter.limit("10/minute")
async def get_data(request: Request):
    return {"data": "value"}

# After (drogue)
from drogue.adapters.fastapi import DrogueLimiter

limiter = DrogueLimiter(app)

@app.get("/api/data")
@limiter.limit("10/minute")
async def get_data():
    return {"data": "value"}

Known Limitations

  • Ban state is in-memory only by default. Redis persistence planned for v0.3.
  • Trust cache is per-process. Multi-worker setups need separate trust state per worker.
  • Flask headers for dict-returning views do not inject automatically.

Security

Report security vulnerabilities via GitHub's private vulnerability reporting. Do not open public issues for security bugs. Response time: 48 hours.


Roadmap

  • v0.1 -- Core rate limiting, DDoS detection, three frameworks (current)
  • v0.2 -- Redis-backed ban state, WebSocket support for Django and Flask
  • v0.3 -- Trust cache cross-process sync, advanced Sentinel features
  • v1.0 -- Production-ready, full documentation site

Development

pip install drogue[dev]
pytest
ruff check src/drogue/

License

MIT License. See LICENSE for details.


Created by Zlynv

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

drogue-0.2.0.tar.gz (115.2 kB view details)

Uploaded Source

Built Distribution

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

drogue-0.2.0-py3-none-any.whl (77.9 kB view details)

Uploaded Python 3

File details

Details for the file drogue-0.2.0.tar.gz.

File metadata

  • Download URL: drogue-0.2.0.tar.gz
  • Upload date:
  • Size: 115.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for drogue-0.2.0.tar.gz
Algorithm Hash digest
SHA256 1781eccacebc1e186d5612ad746b21dcffe74fbe0361e5e5a4c6fa63d8f64072
MD5 6457b36f29c9a3877f213337de680683
BLAKE2b-256 c96f2db118fc3ecbc62c2fb7a4275be58145f25dc9f5277d646d28fca175558a

See more details on using hashes here.

File details

Details for the file drogue-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: drogue-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 77.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for drogue-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3b66759b6bfd656f264a6a956acb07ea5f04665ca84396e6e4b910c9446ba8cf
MD5 e41728e2fad85c7dd867faca02115d23
BLAKE2b-256 0b3726861af27b780c8e9b71a4ff593d6f2889b37fcc564eacb7dcc48fc2ceeb

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