Skip to main content

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

Project description

drogue -- Rate Limiting and DDoS Protection for Python

Python 3.10+ License: MIT Tests

Drop-in replacement for slowapi with DDoS detection, WebSocket support, and 9x faster trusted-user paths.

Author: Zlynv


Why drogue?

slowapi requires request: Request in every endpoint, does not support WebSocket, and has no DDoS detection.

drogue fixes all three:

# slowapi -- polluted signature, no WebSocket, no DDoS detection
@app.get("/api/data")
@limiter.limit("10/minute")
async def get_data(request: Request):  # forced parameter
    return {"data": "value"}

# drogue -- clean signature, WebSocket support, DDoS detection
@app.get("/api/data")
@limiter.limit("10/minute")
async def get_data():  # clean
    return {"data": "value"}

What drogue adds that slowapi does not have:

  • Clean signatures -- no request: Request needed
  • WebSocket rate limiting -- @limiter.limit_ws("100/minute")
  • DDoS detection -- Z-score anomaly detection plus streaming Sentinel Model
  • Early warning -- probe pattern detection 30-120 seconds before attacks
  • Trust caching -- 9x throughput for verified users (5 microseconds vs 43 microseconds)
  • Defense randomization -- attackers cannot learn your thresholds
  • Memory efficient -- 10MB in-process replaces 80MB Redis

Install

pip install drogue

# With framework support
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

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"}

@app.get("/api/heavy")
@limiter.limit("3/minute")  # expensive endpoints get lower limits
async def heavy_operation():
    return {"result": "computed"}

That is it. No request parameter. No middleware setup. Works with Flask and Django too -- see docs/getting-started.


Features

Rate Limiting -- Token Bucket (burst-friendly), Sliding Window (most accurate), Fixed Window (simplest), cost-aware limits, blocking mode

Storage -- In-memory (5 microseconds), Redis (distributed), Count-Min Sketch (10MB for 1M keys)

Frameworks -- FastAPI (pure ASGI middleware), Flask (decorator plus hook), Django (decorator plus middleware)

Protection -- DDoS detection (Z-score plus streaming), probe detection (early warning), progressive auto-ban (5 levels), circuit breaker, CIDR filtering, adaptive limits, shadow mode, trust caching, defense randomization, honeypots

Observability -- Prometheus metrics, OpenTelemetry tracing, structured logging


Performance

Metric drogue Context
Trusted user ~5 microseconds Faster than a function call
Standard user ~43 microseconds 7-23x faster than Redis round-trip
Suspicious user ~200 microseconds Full pipeline, still under 1ms
Throughput 741K req/s Token Bucket, single worker
Memory per key 150 bytes vs 800 bytes in Redis
Count-Min Sketch 10MB Replaces 800MB Redis for 1M keys

Measured on Intel i7-12700K, Python 3.12, asyncio single-worker, median of 10,000 requests.


Migrate from slowapi

Before:

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:

from drogue.adapters.fastapi import DrogueLimiter

limiter = DrogueLimiter(app)

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

Migration checklist:

  1. Replace from slowapi import Limiter with from drogue.adapters.fastapi import DrogueLimiter
  2. Replace Limiter(key_func=get_remote_address) with DrogueLimiter(app)
  3. Remove request: Request from decorated endpoints
  4. Rate limit headers work the same (X-RateLimit-Limit/Remaining/Reset)
  5. Redis config: same URL format, add storage_backend="redis" to config

Competitive Matrix

Feature drogue slowapi Next closest
Cross-framework FastAPI + Flask + Django FastAPI only Django only
Clean signatures Yes No No (rateon only)
WebSocket Yes No No
DDoS detection Yes (Z-score + streaming) No No
Trust caching (9x speedup) Yes No No
Count-Min Sketch Yes (10MB for 1M keys) No No
Geo-blocking No No Yes (fastapi-guard)

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

If you discover a security vulnerability, please open a GitHub issue with the [security] tag. We will respond within 48 hours.


Roadmap

  • 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

git clone https://github.com/Zlynv/drogue.git
cd drogue
pip install -e ".[dev]"

# Run tests
pytest

# Run linting
ruff check src/drogue/

# Run integration tests
cd _integration_test && pip install -r requirements.txt && pytest

License

MIT License. See LICENSE for details.


Author

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.1.0.tar.gz (93.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.1.0-py3-none-any.whl (71.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: drogue-0.1.0.tar.gz
  • Upload date:
  • Size: 93.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.1.0.tar.gz
Algorithm Hash digest
SHA256 e84e23cdd9903c09850ca028f6e0cb977915cf5ee7428022776a5c7866e764d3
MD5 c33ed5729dfd59aeccc18d9022431663
BLAKE2b-256 ea427bb998c56411bc81bd483957bd1a52ac8651a6ab72f3d67f447a04bf6df6

See more details on using hashes here.

File details

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

File metadata

  • Download URL: drogue-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 71.8 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e76dc7083d971c3dcf2b5cef6fed266d7c3cb22f5d886ddb84a2dc00084b341d
MD5 163ba416301139806833e53fa901bfe6
BLAKE2b-256 6d152b7e44b37c5a41a23c07ff7cadf97730111bb886e2743e07cc2e09ae1b58

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