Rate Limiter
dagster_authkit.auth.rate_limiter
Rate Limiter - Brute Force Protection
Supports both in-memory (single-pod) and Redis (distributed) backends.
RateLimiterBackend
Bases: ABC
Abstract rate limiter backend.
is_rate_limited
abstractmethod
is_rate_limited(identifier, max_attempts, window_seconds)
Check if identifier is rate limited.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identifier
|
str
|
Username or IP address |
required |
max_attempts
|
int
|
Maximum attempts allowed |
required |
window_seconds
|
int
|
Time window in seconds |
required |
Returns:
| Type | Description |
|---|---|
Tuple[bool, int]
|
Tuple[bool, int]: (is_limited, attempts_count) |
record_attempt
abstractmethod
record_attempt(identifier, window_seconds)
Record a failed attempt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identifier
|
str
|
Username or IP address |
required |
window_seconds
|
int
|
Time window in seconds |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
Current attempt count |
check_and_record
abstractmethod
check_and_record(identifier, max_attempts, window_seconds)
Atomically check if rate limited and record an attempt.
Eliminates the TOCTOU race between is_rate_limited() and record_attempt() when called separately.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identifier
|
str
|
Username or IP address |
required |
max_attempts
|
int
|
Maximum attempts allowed |
required |
window_seconds
|
int
|
Time window in seconds |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Tuple[bool, int]: (is_limited, attempts_count) |
int
|
Unlike check_and_record on the facade, this does NOT skip |
Tuple[bool, int]
|
recording when already limited — the atomic operation records |
Tuple[bool, int]
|
and checks in one step, returning the post-recording state. |
reset
abstractmethod
reset(identifier)
Reset attempts for identifier (after successful login).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identifier
|
str
|
Username or IP address |
required |
InMemoryRateLimiter
Bases: RateLimiterBackend
In-memory rate limiter (single-pod only).
WARNING: Does NOT work across multiple pods/instances! Each pod has its own memory, so rate limits are not shared.
Use RedisRateLimiter for distributed deployments.
__init__
__init__()
Initialise thread-safe in-memory attempt store with OOM protection.
is_rate_limited
is_rate_limited(identifier, max_attempts, window_seconds)
Check if identifier is rate limited.
check_and_record
check_and_record(identifier, max_attempts, window_seconds)
Atomically check and record an attempt. Holds the lock once.
record_attempt
record_attempt(identifier, window_seconds)
Record failed attempt.
reset
reset(identifier)
Reset counter after successful login.
RedisRateLimiter
Bases: RateLimiterBackend
Redis-backed rate limiter (distributed, multi-pod safe).
Uses Redis INCR + EXPIRE for atomic operations. Works correctly across multiple pods/instances.
__init__
__init__(redis_url)
Initialise Redis connection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
redis_url
|
str
|
Redis connection URL ( |
required |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the |
is_rate_limited
is_rate_limited(identifier, max_attempts, window_seconds)
Check if identifier is rate limited.
check_and_record
check_and_record(identifier, max_attempts, window_seconds)
Atomically check and record via Lua script.
reset
reset(identifier)
Reset attempts after successful login.
RateLimiter
Main rate limiter class (facade pattern).
Automatically selects backend based on configuration: - Redis if DAGSTER_AUTH_REDIS_URL is set - In-memory otherwise (with warning for multi-pod)
__init__
__init__(max_attempts=5, window_seconds=300, enabled=True, redis_url=None)
Initialise the rate limiter, auto-selecting the backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_attempts
|
int
|
Maximum allowed attempts within the window. |
5
|
window_seconds
|
int
|
Time window in seconds. |
300
|
enabled
|
bool
|
If |
True
|
redis_url
|
Optional[str]
|
Redis connection URL. Auto-detected from
|
None
|
check_and_record
check_and_record(identifier)
Atomically check if rate limited and record an attempt.
Delegates to the backend's atomic check_and_record, which eliminates the TOCTOU race between is_rate_limited() and record_attempt() when called separately.
Returns:
| Type | Description |
|---|---|
bool
|
Tuple[bool, int]: (is_limited, attempts_count) |
int
|
If is_limited is True, the attempt was recorded but |
Tuple[bool, int]
|
the user exceeded the limit. |
record_attempt
record_attempt(identifier)
Record a failed login attempt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identifier
|
str
|
Username or IP address |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
Current attempt count |
is_rate_limited
is_rate_limited(identifier)
Check if identifier is rate limited.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identifier
|
str
|
Username or IP address |
required |
Returns:
| Type | Description |
|---|---|
Tuple[bool, int]
|
Tuple[bool, int]: (is_limited, attempts_count) |
reset
reset(identifier)
Reset attempts for identifier (after successful login).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
identifier
|
str
|
Username or IP address |
required |
get_rate_limiter
get_rate_limiter()
Get rate limiter singleton (thread-safe with double-checked locking).
Returns:
| Type | Description |
|---|---|
RateLimiter
|
Global RateLimiter instance |
record_login_attempt
record_login_attempt(username)
Record failed login attempt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
username
|
str
|
Username |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
Current attempt count |
is_rate_limited
is_rate_limited(username)
Check if username is rate limited.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
username
|
str
|
Username |
required |
Returns:
| Type | Description |
|---|---|
Tuple[bool, int]
|
Tuple[bool, int]: (is_limited, attempts_count) |
reset_rate_limit
reset_rate_limit(username)
Reset rate limit after successful login.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
username
|
str
|
Username |
required |