Skip to main content

Django RateLatch

A configurable Django rate-limiting library with middleware, per-view decorators, and Django REST Framework throttle support.

Choose fixed-window, sliding-window-counter, or token-bucket rate limiting. Store state in memory for single-process use, or in Redis for shared use across processes and servers.

Use it to apply limits across a Django project, selected views, or DRF endpoints.

Features

  • Apply a rate limit across Django requests with middleware.
  • Apply limits to selected views with a decorator.
  • Integrate with Django REST Framework using a throttle class.
  • Choose between fixed-window, sliding-window-counter, and token-bucket algorithms.
  • Use in-memory or Redis storage.
  • Return HTTP 429 responses with a Retry-After header when a request is rejected.
  • Configure behavior for rate-limiter backend failures.

Requirements

  • Python 3.11 or newer
  • Django 5.2 or newer

The optional Django REST Framework integration requires Django REST Framework. The optional Redis backend requires the redis Python client and a reachable Redis server.

Installation

With pip:

python -m pip install django-ratelatch

With uv:

uv add django-ratelatch

Optional integrations

Install the Redis extra if using the Redis backend:

python -m pip install "django-ratelatch[redis]"
uv add "django-ratelatch[redis]"

Install the DRF extra if using the Django REST Framework integration:

python -m pip install "django-ratelatch[drf]"
uv add "django-ratelatch[drf]"

To install both extras:

python -m pip install "django-ratelatch[redis,drf]"
uv add "django-ratelatch[redis,drf]"

The Redis extra installs the Python client. It does not install or run a Redis server.

Configuration

Define a key function in your Django project. Requests that return the same key share a rate limit.

# my_project/rate_limit_key.py
def get_rate_limit_key(request):
    if request.user.is_authenticated:
        return f"user:{request.user.pk}"

    return f"ip:{request.META.get('REMOTE_ADDR', '')}"

Add a RATE_LIMITER setting to your Django project's settings.py:

RATE_LIMITER = {
    "ALGORITHM": "fixed_window",
    "LIMIT": 10,
    "WINDOW_SECONDS": 60,
    "KEY_FUNCTION": "my_project.rate_limit_key.get_rate_limit_key",
    "BACKEND": "memory",
}

KEY_FUNCTION is a dotted Python path to a function that accepts a Django request and returns a client key.

Use Redis storage

For applications served by multiple processes or servers, configure Redis so they share rate-limit state:

import os

RATE_LIMITER["BACKEND"] = "redis"
RATE_LIMITER["REDIS_URL"] = os.environ["RATE_LIMITER_REDIS_URL"]

Set RATE_LIMITER_REDIS_URL in the environment where Django runs, for example:

redis://localhost:6379/0

Optional Redis connection timeouts are specified in seconds and default to 1.0:

RATE_LIMITER["REDIS_SOCKET_TIMEOUT"] = 1.0
RATE_LIMITER["REDIS_CONNECT_TIMEOUT"] = 1.0

Configuration options

Setting Meaning
ALGORITHM fixed_window, sliding_window_counter, or token_bucket.
LIMIT For fixed and sliding-window algorithms, the maximum requests per window. For token bucket, the number of tokens replenished per window.
WINDOW_SECONDS The window or refill period, in seconds.
KEY_FUNCTION Dotted path to the function that returns a client key.
BACKEND memory or redis.
REDIS_URL Redis connection URL. Required when BACKEND is redis.
BURST_CAPACITY Maximum tokens in the bucket. Token-bucket only; defaults to LIMIT.
FAIL_OPEN Whether to allow requests if the backend fails. Defaults to False.
REDIS_SOCKET_TIMEOUT Redis socket timeout in seconds. Defaults to 1.0.
REDIS_CONNECT_TIMEOUT Redis connection timeout in seconds. Defaults to 1.0.

Choosing a client key

The key function determines which requests share a limit. Common choices include an authenticated user ID, an API key, or a client IP address.

If Django is behind a reverse proxy, REMOTE_ADDR may be the proxy address rather than the original client's address. Use a key function that reads the client IP from a header only when your proxy is configured to set and protect that header.

Use as middleware

Add the middleware to your Django project's MIDDLEWARE setting:

MIDDLEWARE = [
    # ...
    "django_ratelatch.integrations.middleware.RateLimitMiddleware",
]

The middleware applies the configured algorithm, limit, backend, and key function to requests handled by the project.

Use as a view decorator

Use the decorator to limit selected views instead of applying the middleware to every request:

from django_ratelatch.integrations.decorator import rate_limit


@rate_limit()
def my_view(request):
    ...

With no argument, the decorator uses the RATE_LIMITER settings.

Pass a rate string to override the limit and window for that view. The algorithm, backend, and key function still come from RATE_LIMITER:

@rate_limit("10/m")
def another_view(request):
    ...

Supported time units include seconds (s, sec), minutes (m, min), and hours (h, hr). A multiplier is supported, for example "30/150s".

Avoid applying both the middleware and decorator to the same request path unless you intend for both checks to run.

Use with Django REST Framework

Install the drf extra, then add rest_framework to INSTALLED_APPS:

INSTALLED_APPS = [
    # ...
    "rest_framework",
]

Configure the rate-limiter throttle as a default DRF throttle:

REST_FRAMEWORK = {
    "DEFAULT_THROTTLE_CLASSES": [
        "django_ratelatch.integrations.drf.RateLimitThrottle",
    ],
}

The throttle uses the RATE_LIMITER settings and key function described above. Throttled requests receive HTTP 429 and a Retry-After header.

If the middleware and DRF throttle both process the same API request, both checks run. Choose the integration that fits the endpoints you want to limit.

Algorithms

  • Fixed window counts requests in aligned time windows. Counters reset when a new window starts.
  • Sliding window counter estimates usage across a rolling window using counts from the current and previous windows. It uses less state than a sliding-window log, but the count is an approximation.
  • Token bucket replenishes tokens at a steady rate and allows requests while tokens are available. BURST_CAPACITY controls how many requests can be accepted in a burst.

Storage and backend failures

The in-memory backend is process-local. Its state is not shared between separate worker processes or servers. Use Redis when those processes must share limits.

When the backend fails, FAIL_OPEN controls the integration behavior:

  • False (default): fail closed. Middleware and the decorator return HTTP 503; the DRF integration raises a 503 API exception.
  • True: fail open. The request proceeds without a rate-limit decision.

Supported versions

The test suite runs on supported Python/Django combinations for Python 3.11–3.14 and Django 5.2, 6.0, and 6.1.

Development

Clone the repository, then install the development dependencies:

uv sync --all-extras --dev

Run the test suite with:

uv run pytest

Redis integration tests require a Redis server and RATE_LIMITER_REDIS_URL. The Redis middleware integration test is skipped when that environment variable is not set.

License

This project is licensed under the MIT License. See LICENSE.

Metadata

Release files for django-ratelatch 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-ratelatch 0.1.0
File Size Uploaded
django_ratelatch-0.1.0.tar.gz 9.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-ratelatch 0.1.0
File Interpreter ABI Platform
django_ratelatch-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 24.8 kB

Release files / django_ratelatch-0.1.0.tar.gz

Download URL django_ratelatch-0.1.0.tar.gz
Size 9.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d684b452ca02cb26c5f09cb382a2f1ec56918ffdd564c51a363619e8c991febc
BLAKE2b-256 checksum
How to use checksums
aec92e7687c93716481d6a707f0693626227e5ef3fc48976541e38099a45c719
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / django_ratelatch-0.1.0-py3-none-any.whl

Download URL django_ratelatch-0.1.0-py3-none-any.whl
Size 15.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1dc574d635a1ee4226985571504377d8b20ea0c45d55642240b839dfc2c399d0
BLAKE2b-256 checksum
How to use checksums
987dc709de65a47e2dab2028034d2da3c9de30f2c9ac5d61e9d8eac3a3de12cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page