<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: zlynv</title>
    <description>The latest articles on DEV Community by zlynv (@zlynv).</description>
    <link>https://dev.to/zlynv</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4052266%2F75616013-6b75-4822-a09f-d9552606335f.png</url>
      <title>DEV Community: zlynv</title>
      <link>https://dev.to/zlynv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zlynv"/>
    <language>en</language>
    <item>
      <title>Building a Modern Rate Limiter and DDoS Protection Library for Python</title>
      <dc:creator>zlynv</dc:creator>
      <pubDate>Wed, 29 Jul 2026 03:31:10 +0000</pubDate>
      <link>https://dev.to/zlynv/building-a-modern-rate-limiter-and-ddos-protection-library-for-python-49fe</link>
      <guid>https://dev.to/zlynv/building-a-modern-rate-limiter-and-ddos-protection-library-for-python-49fe</guid>
      <description>&lt;p&gt;Rate limiting is one of those features every production API eventually needs.&lt;/p&gt;

&lt;p&gt;Whether you're building a public REST API, a WebSocket service, or an authentication endpoint, you'll eventually face problems like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Credential stuffing&lt;/li&gt;
&lt;li&gt;Brute-force attacks&lt;/li&gt;
&lt;li&gt;API abuse&lt;/li&gt;
&lt;li&gt;Bots scraping your endpoints&lt;/li&gt;
&lt;li&gt;Unexpected traffic spikes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most applications solve this with a simple request counter.&lt;/p&gt;

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

&lt;p&gt;That observation led me to build &lt;strong&gt;drogue&lt;/strong&gt;, an open-source Python library for rate limiting and traffic protection.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Traditional rate limiting is straightforward:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Allow 100 requests per minute.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This works well for many cases, but real-world applications quickly expose its limitations.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A distributed attack can remain below the per-IP limit.&lt;/li&gt;
&lt;li&gt;A bot can rotate through proxies.&lt;/li&gt;
&lt;li&gt;WebSocket connections often require different handling than HTTP requests.&lt;/li&gt;
&lt;li&gt;Different endpoints need different protection strategies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted a system that could go beyond simple request counting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Goals
&lt;/h2&gt;

&lt;p&gt;From the beginning, I focused on a few principles.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Clean framework integration
&lt;/h3&gt;

&lt;p&gt;I didn't want endpoint functions filled with framework-specific plumbing.&lt;/p&gt;

&lt;p&gt;Instead, the library should feel like a natural extension of the framework.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;drogue.adapters.fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DrogueLimiter&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DrogueLimiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default_limits&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;100/minute&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@limiter.limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10/minute&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;users&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No additional request objects.&lt;br&gt;
No complicated middleware configuration.&lt;br&gt;
Minimal boilerplate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple Rate Limiting Algorithms
&lt;/h2&gt;

&lt;p&gt;Different applications require different algorithms.&lt;/p&gt;

&lt;p&gt;Instead of supporting only one approach, drogue includes multiple options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token Bucket&lt;/li&gt;
&lt;li&gt;Sliding Window&lt;/li&gt;
&lt;li&gt;Fixed Window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each has different trade-offs between accuracy, burst handling, and memory usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond Rate Limiting
&lt;/h2&gt;

&lt;p&gt;One thing I kept noticing was that abusive traffic often doesn't violate the configured limits.&lt;/p&gt;

&lt;p&gt;An attacker may intentionally stay below the threshold.&lt;/p&gt;

&lt;p&gt;That's why I started experimenting with additional protection mechanisms such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traffic anomaly detection&lt;/li&gt;
&lt;li&gt;Progressive temporary bans&lt;/li&gt;
&lt;li&gt;Probe detection&lt;/li&gt;
&lt;li&gt;Circuit breakers&lt;/li&gt;
&lt;li&gt;CIDR filtering&lt;/li&gt;
&lt;li&gt;Shadow mode for safely testing rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rather than replacing traditional rate limiting, these features complement it.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebSocket Support
&lt;/h2&gt;

&lt;p&gt;Many existing rate limiting solutions primarily focus on HTTP.&lt;/p&gt;

&lt;p&gt;Modern applications increasingly rely on WebSockets for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chat applications&lt;/li&gt;
&lt;li&gt;Live dashboards&lt;/li&gt;
&lt;li&gt;Multiplayer games&lt;/li&gt;
&lt;li&gt;Real-time notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Supporting both HTTP and WebSocket traffic from the same library became an important design goal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Framework Support
&lt;/h2&gt;

&lt;p&gt;Currently, drogue provides adapters for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Django&lt;/li&gt;
&lt;li&gt;Django REST Framework&lt;/li&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;Flask&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to keep the developer experience as consistent as possible across frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Performance matters because rate limiting runs on every request.&lt;/p&gt;

&lt;p&gt;The core package is designed with minimal overhead while keeping the implementation extensible enough for different storage backends and deployment scenarios.&lt;/p&gt;

&lt;p&gt;Performance testing and optimization remain an ongoing part of development, and I plan to continue publishing benchmark improvements as the project evolves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Building this project taught me several things:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;There are still many ideas I'd like to explore, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Additional storage backends&lt;/li&gt;
&lt;li&gt;More adaptive protection strategies&lt;/li&gt;
&lt;li&gt;Better observability&lt;/li&gt;
&lt;li&gt;Additional framework integrations&lt;/li&gt;
&lt;li&gt;More comprehensive benchmarking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I'd Love Your Feedback
&lt;/h2&gt;

&lt;p&gt;This project is still evolving, and feedback from the Python community is incredibly valuable.&lt;/p&gt;

&lt;p&gt;If you build production APIs with Django, FastAPI, Flask, or another Python framework, I'd love to hear your thoughts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What features do you look for in a rate limiting library?&lt;/li&gt;
&lt;li&gt;What challenges have you encountered protecting public APIs?&lt;/li&gt;
&lt;li&gt;Is there something missing that would make a library like this more useful?&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The project is open source, and contributions, suggestions, and constructive criticism are always welcome.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/zlynv/drogue" rel="noopener noreferrer"&gt;https://github.com/zlynv/drogue&lt;/a&gt;&lt;br&gt;
Documentation: &lt;a href="https://zlynv.github.io/drogue/" rel="noopener noreferrer"&gt;https://zlynv.github.io/drogue/&lt;/a&gt;&lt;br&gt;
PyPI: &lt;code&gt;pip install drogue&lt;/code&gt;&lt;/p&gt;

</description>
      <category>fastapi</category>
      <category>django</category>
      <category>flask</category>
      <category>python</category>
    </item>
  </channel>
</rss>
