zlynv

Rate limiting is one of those features every production API eventually needs.

Whether you're building a public REST API, a WebSocket service, or an authentication endpoint, you'll eventually face problems like:

  • Credential stuffing
  • Brute-force attacks
  • API abuse
  • Bots scraping your endpoints
  • Unexpected traffic spikes

Most applications solve this with a simple request counter.

But after building several APIs with Django, FastAPI, and Flask, I realized that production traffic requires much more than "X requests per minute."

That observation led me to build drogue, an open-source Python library for rate limiting and traffic protection.

The Problem

Traditional rate limiting is straightforward:

Allow 100 requests per minute.

This works well for many cases, but real-world applications quickly expose its limitations.

For example:

  • A distributed attack can remain below the per-IP limit.
  • A bot can rotate through proxies.
  • WebSocket connections often require different handling than HTTP requests.
  • Different endpoints need different protection strategies.

I wanted a system that could go beyond simple request counting.

Design Goals

From the beginning, I focused on a few principles.

1. Clean framework integration

I didn't want endpoint functions filled with framework-specific plumbing.

Instead, the library should feel like a natural extension of the framework.

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

app = FastAPI()

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

@app.get("/users")
@limiter.limit("10/minute")
async def users():
    return {"status": "ok"}

Enter fullscreen mode Exit fullscreen mode

No additional request objects.
No complicated middleware configuration.
Minimal boilerplate.

Multiple Rate Limiting Algorithms

Different applications require different algorithms.

Instead of supporting only one approach, drogue includes multiple options:

  • Token Bucket
  • Sliding Window
  • Fixed Window

Each has different trade-offs between accuracy, burst handling, and memory usage.

Beyond Rate Limiting

One thing I kept noticing was that abusive traffic often doesn't violate the configured limits.

An attacker may intentionally stay below the threshold.

That's why I started experimenting with additional protection mechanisms such as:

  • Traffic anomaly detection
  • Progressive temporary bans
  • Probe detection
  • Circuit breakers
  • CIDR filtering
  • Shadow mode for safely testing rules

Rather than replacing traditional rate limiting, these features complement it.

WebSocket Support

Many existing rate limiting solutions primarily focus on HTTP.

Modern applications increasingly rely on WebSockets for:

  • Chat applications
  • Live dashboards
  • Multiplayer games
  • Real-time notifications

Supporting both HTTP and WebSocket traffic from the same library became an important design goal.

Framework Support

Currently, drogue provides adapters for:

  • Django
  • Django REST Framework
  • FastAPI
  • Flask

The goal is to keep the developer experience as consistent as possible across frameworks.

Performance

Performance matters because rate limiting runs on every request.

The core package is designed with minimal overhead while keeping the implementation extensible enough for different storage backends and deployment scenarios.

Performance testing and optimization remain an ongoing part of development, and I plan to continue publishing benchmark improvements as the project evolves.

Lessons Learned

Building this project taught me several things:

  • Good APIs are often harder to design than efficient algorithms.
  • Framework integration significantly affects developer experience.
  • Rate limiting alone isn't enough for many production environments.
  • Clear documentation is just as important as clean code.
  • Simplicity usually wins over feature overload.

What's Next

There are still many ideas I'd like to explore, including:

  • Additional storage backends
  • More adaptive protection strategies
  • Better observability
  • Additional framework integrations
  • More comprehensive benchmarking

I'd Love Your Feedback

This project is still evolving, and feedback from the Python community is incredibly valuable.

If you build production APIs with Django, FastAPI, Flask, or another Python framework, I'd love to hear your thoughts.

  • What features do you look for in a rate limiting library?
  • What challenges have you encountered protecting public APIs?
  • Is there something missing that would make a library like this more useful?

The project is open source, and contributions, suggestions, and constructive criticism are always welcome.

Building infrastructure libraries is always a balancing act between performance, flexibility, and developer experience. Drogue is my attempt to make API protection easier without sacrificing clean application code.

If you're building production APIs with Django, FastAPI, Flask, or another Python framework, I'd love to hear your thoughts. Whether it's an issue, feature request, benchmark, or pull request, your feedback will help shape the project.

GitHub: https://github.com/zlynv/drogue
Documentation: https://zlynv.github.io/drogue/
PyPI: pip install drogue