How to Implement a Rate Limiter in Python

A beginner-friendly Python class that tracks call timestamps with a deque to allow or block calls based on a max rate per time period.

Easy Python 3.9+ Aug 9, 2026 Reliability & rate limiting 16 views 0 copies

Python code

31 lines
Python 3.9+
import time
from collections import deque


class RateLimiter:
    """Simple rate limiter for beginners."""

    def __init__(self, max_calls: int, period_seconds: float):
        self.max_calls = max_calls
        self.period = period_seconds
        self.calls = deque()

    def allow(self) -> bool:
        """Return True if a call is allowed, False otherwise."""
        now = time.monotonic()
        while self.calls and now - self.calls[0] >= self.period:
            self.calls.popleft()
        if len(self.calls) < self.max_calls:
            self.calls.append(now)
            return True
        return False


if __name__ == "__main__":
    limiter = RateLimiter(max_calls=3, period_seconds=1.0)

    for i in range(5):
        print(f"Call {i + 1}: {'allowed' if limiter.allow() else 'blocked'}")
    time.sleep(1.0)
    print("After 1 second:")
    print(f"Call 6: {'allowed' if limiter.allow() else 'blocked'}")

Output

stdout
Call 1: allowed
Call 2: allowed
Call 3: allowed
Call 4: blocked
Call 5: blocked
After 1 second:
Call 6: allowed

How it works

The RateLimiter uses a deque to store timestamps of recent calls. time.monotonic() gives a stable clock that never jumps, so rate limiting stays accurate. On each allow() check, it removes timestamps older than the period, then checks if the current count is below the limit. If so, it records the current time and returns True; otherwise, it returns False. This sliding-window approach is simple, memory‑efficient, and works for any rate limit pattern in small applications.

Common mistakes

  • Using `time.time()` instead of `time.monotonic()` — wall clock changes can break the limiter.
  • Forgetting that `deque` is not thread‑safe — for concurrent use, wrap calls with a lock.
  • Not pruning old timestamps, causing memory growth and inaccurate counts.

Variations

  1. Use a fixed‑window counter with a start timestamp and reset when the window expires.
  2. Use a token bucket algorithm with a background refill for smoother burst control.

Real-world use cases

  • Limiting API requests from a CLI script so you respect a third‑party rate limit.
  • Throttling user actions in a web app to prevent spam, e.g., login attempts or form submissions.
  • Capping the number of external calls a background worker makes per second to avoid overloading a downstream service.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Reliability & rate limiting

Related tutorials and quizzes for this topic.