Python Rate-Limiter using Leaky-Bucket Algorithm for controlling request rates in applications with multiple backend storage options.
npx @tessl/cli install tessl/pypi-pyrate-limiter@3.9.00
# PyrateLimiter
1
2
A comprehensive Python rate-limiting library implementing the Leaky Bucket algorithm for controlling request rates in applications. PyrateLimiter supports unlimited rate limits with custom intervals, separately tracks limits for different services or resources, and manages limit breaches through configurable exception raising or delay mechanisms.
3
4
The library offers both synchronous and asynchronous workflows with multiple backend options including in-memory, Redis, SQLite, and PostgreSQL storage for persistent rate limiting across threads, processes, or application restarts. Key features include decorator support for easy function wrapping, multiprocessing compatibility, weight-based item consumption, and extensible architecture allowing custom bucket implementations.
5
6
## Package Information
7
8
- **Package Name**: pyrate-limiter
9
- **Language**: Python
10
- **Installation**: `pip install pyrate-limiter`
11
- **Version**: 3.9.0
12
- **License**: MIT
13
14
## Core Imports
15
16
```python
17
import pyrate_limiter
18
```
19
20
Common usage imports:
21
22
```python
23
from pyrate_limiter import Limiter, Rate, Duration, BucketFullException
24
from pyrate_limiter import InMemoryBucket, SQLiteBucket, RedisBucket
25
```
26
27
## Basic Usage
28
29
```python
30
from pyrate_limiter import Limiter, Rate, Duration
31
32
# Create a limiter: 5 requests per second
33
limiter = Limiter(Rate(5, Duration.SECOND))
34
35
# Try to acquire permission for a request
36
if limiter.try_acquire("user123"):
37
print("Request allowed")
38
else:
39
print("Rate limit exceeded")
40
41
# Using with context manager
42
with Limiter(Rate(10, Duration.MINUTE)) as limiter:
43
success = limiter.try_acquire("api_call", weight=2)
44
45
# Using as decorator
46
@limiter.as_decorator()
47
def rate_limited_function(user_id):
48
return (user_id, 1) # (name, weight) for rate limiting
49
50
@rate_limited_function
51
def api_call(user_id):
52
return f"Processing request for {user_id}"
53
```
54
55
## Architecture
56
57
PyrateLimiter uses a modular architecture based on three core abstractions:
58
59
- **Rate**: Defines rate limit rules (limit/interval pairs)
60
- **Bucket**: Storage backend for tracking rate limit state (in-memory, SQLite, Redis, PostgreSQL)
61
- **Clock**: Time source for rate calculations (system time, monotonic, remote database time)
62
- **Limiter**: Orchestrates rate limiting logic using buckets and clocks
63
64
This design enables flexible deployment scenarios from simple in-process rate limiting to distributed systems with shared state across multiple application instances.
65
66
## Capabilities
67
68
### Core Rate Limiting
69
70
The main Limiter class provides the primary rate limiting functionality with support for both synchronous and asynchronous operations, configurable delays, and exception handling.
71
72
```python { .api }
73
class Limiter:
74
def __init__(
75
self,
76
argument: Union[BucketFactory, AbstractBucket, Rate, List[Rate]],
77
clock: Optional[AbstractClock] = None,
78
raise_when_fail: bool = True,
79
max_delay: Optional[Union[int, Duration]] = None,
80
retry_until_max_delay: bool = False,
81
buffer_ms: int = 50
82
): ...
83
84
def try_acquire(self, name: str, weight: int = 1) -> Union[bool, Awaitable[bool]]: ...
85
86
async def try_acquire_async(self, name: str, weight: int = 1) -> bool: ...
87
88
def as_decorator(self) -> Callable[[ItemMapping], DecoratorWrapper]: ...
89
```
90
91
[Core Rate Limiting](./core-limiting.md)
92
93
### Storage Backends
94
95
Multiple storage backends for persisting rate limit state across application restarts, processes, and distributed deployments.
96
97
```python { .api }
98
class InMemoryBucket(AbstractBucket):
99
def __init__(self, rates: List[Rate]): ...
100
101
class SQLiteBucket(AbstractBucket):
102
def __init__(self, rates: List[Rate], conn: sqlite3.Connection, table: str, lock: Optional[RLock] = None): ...
103
104
@classmethod
105
def init_from_file(
106
cls, rates: List[Rate], db_path: str, table: str = "pyrate_limiter",
107
create_new_table: bool = False, use_file_lock: bool = False
108
) -> "SQLiteBucket": ...
109
110
class RedisBucket(AbstractBucket):
111
def __init__(self, rates: List[Rate], redis: Union[Redis, AsyncRedis], bucket_key: Optional[str] = None): ...
112
```
113
114
[Storage Backends](./storage-backends.md)
115
116
### Rate Configuration
117
118
Rate definition and duration utilities for configuring rate limits with flexible time intervals and validation.
119
120
```python { .api }
121
class Rate:
122
def __init__(self, limit: int, interval: Union[int, Duration]): ...
123
124
class Duration(Enum):
125
SECOND = 1000
126
MINUTE = 60000
127
HOUR = 3600000
128
DAY = 86400000
129
WEEK = 604800000
130
```
131
132
[Rate Configuration](./rate-configuration.md)
133
134
### Factory Patterns
135
136
Pre-configured factory functions and patterns for common use cases including multiprocessing support and simplified bucket creation.
137
138
```python { .api }
139
def create_limiter(
140
rate_per_duration: int = 3,
141
duration: Union[int, Duration] = Duration.SECOND,
142
clock: Optional[AbstractClock] = None,
143
**limiter_kwargs
144
) -> Limiter: ...
145
146
def create_sqlite_limiter(
147
rate_per_duration: int = 3,
148
duration: Union[int, Duration] = Duration.SECOND,
149
db_path: Optional[str] = None,
150
**kwargs
151
) -> Limiter: ...
152
```
153
154
[Factory Patterns](./factory-patterns.md)
155
156
### Time Sources
157
158
Different clock implementations for various deployment scenarios including local system time, monotonic time, and remote database-backed time sources.
159
160
```python { .api }
161
class TimeClock(AbstractClock):
162
def now(self) -> int: ...
163
164
class MonotonicClock(AbstractClock):
165
def now(self) -> int: ...
166
167
class SQLiteClock(AbstractClock):
168
def __init__(self, conn: Union[sqlite3.Connection, SQLiteBucket]): ...
169
```
170
171
[Time Sources](./time-sources.md)
172
173
## Exception Handling
174
175
```python { .api }
176
class BucketFullException(Exception):
177
def __init__(self, item: RateItem, rate: Rate): ...
178
item: RateItem
179
rate: Rate
180
meta_info: Dict[str, Union[str, float]]
181
182
class LimiterDelayException(Exception):
183
def __init__(self, item: RateItem, rate: Rate, actual_delay: int, max_delay: int): ...
184
item: RateItem
185
rate: Rate
186
actual_delay: int
187
max_delay: int
188
meta_info: Dict[str, Union[str, float]]
189
```
190
191
## Utility Functions
192
193
Utility functions for rate limiting operations and validation.
194
195
```python { .api }
196
def binary_search(items: List[RateItem], value: int) -> int:
197
"""
198
Find the index of item in list where left.timestamp < value <= right.timestamp.
199
200
Used internally to determine current size of time windows for rate calculations.
201
202
Parameters:
203
- items: List of RateItem objects sorted by timestamp
204
- value: Timestamp value to search for
205
206
Returns:
207
- int: Index position for the timestamp boundary
208
"""
209
210
def validate_rate_list(rates: List[Rate]) -> bool:
211
"""
212
Validate that rates are correctly ordered for rate limiting.
213
214
Parameters:
215
- rates: List of Rate objects to validate
216
217
Returns:
218
- bool: True if rates are valid, False otherwise
219
220
Validation rules:
221
- Rates must be ordered by increasing interval
222
- Rates must be ordered by increasing limit
223
- Rate density (limit/interval) must be decreasing
224
"""
225
226
def id_generator(size: int = 6, chars: str = ...) -> str:
227
"""
228
Generate random string identifier.
229
230
Parameters:
231
- size: Length of generated string (default: 6)
232
- chars: Character set to use (default: alphanumeric)
233
234
Returns:
235
- str: Random string identifier
236
"""
237
238
def dedicated_sqlite_clock_connection() -> sqlite3.Connection:
239
"""
240
Create dedicated SQLite connection for clock operations.
241
242
Returns:
243
- sqlite3.Connection: Configured SQLite connection for time queries
244
245
Features:
246
- Uses temporary database file
247
- Configured for EXCLUSIVE isolation
248
- Thread-safe with check_same_thread=False
249
"""
250
```
251
252
## Core Types
253
254
```python { .api }
255
class RateItem:
256
def __init__(self, name: str, timestamp: int, weight: int = 1): ...
257
name: str
258
weight: int
259
timestamp: int
260
261
ItemMapping = Callable[[Any], Tuple[str, int]]
262
DecoratorWrapper = Callable[[Callable[[Any], Any]], Callable[[Any], Any]]
263
```