Skip to content

FAQ

Why is Redis a hard requirement, not an optional backend?

Correct distributed rate limiting needs an atomic, shared, low-latency read-modify-write primitive — Redis's Lua scripting (EVAL) is exactly that. A database-backed alternative (like drf-idempotency offers) would need per-request row locking or unique-constraint tricks that don't map cleanly onto "count requests per rolling time window" the way they do onto "claim this key exactly once" — so this package doesn't pretend to offer a database fallback.

Does this replace DRF's built-in throttles?

Not necessarily — rate_limit()-produced throttles are regular BaseThrottle subclasses, so they coexist fine with UserRateThrottle, AnonRateThrottle, or ScopedRateThrottle in the same throttle_classes list if you have a reason to keep both. Most projects migrating fully to this package simply replace the built-in ones for the extra algorithm choice, burst handling, and header support.

What happens if I don't add RateLimitHeadersMixin?

Throttling still works fully — 429/Retry-After come from DRF's own Throttled exception regardless. You just won't get the informational RateLimit-Limit/RateLimit-Remaining/RateLimit-Reset headers on successful responses.

Can I use this outside DRF, in plain Django views?

The algorithm functions (token_bucket_check, etc.) have no DRF dependency — call them directly from any Python code, including a plain Django view. rate_limit()/RateLimitThrottle/RateLimitHeadersMixin are DRF-specific (they build on BaseThrottle and finalize_response()), so for a non-DRF view you'd call the algorithm function yourself and handle the 429 response manually.

How is this different from django-ratelimit?

django-ratelimit targets plain Django views with a decorator-first API and (typically) Django's cache framework as a backend. This package is DRF-native (built on BaseThrottle, composes with permission_classes/ authentication_classes/other throttles automatically), Redis-first (for genuine distributed atomicity and Cluster support), and offers token bucket/sliding window algorithms with real burst handling that a cache-backed fixed-window counter can't provide.

Does cost=0 let me "peek" at the current state without consuming budget?

Yes for token bucket (a true no-op check). Fixed/sliding window with cost=0 also don't consume budget, but as a side effect may initialize a counter key for a previously-unseen identity (setting its TTL) even though no real request occurred — a minor, harmless quirk of how the underlying INCRBY 0 command behaves on a non-existent key. See Advanced Usage.

Is there a way to reset a specific key manually?

Not as public API today, but straightforward via the client directly for an operational/debugging scenario:

from drf_ratelimit_plus.client import get_redis_client
from drf_ratelimit_plus.settings import get_setting

get_redis_client().delete(f"{get_setting('KEY_PREFIX')}token_bucket:some-scope:user:42")

(Match the key format your configured algorithm/scope/key function actually produces — see Architecture for how keys are built.)