Skip to main content

LLMRateLimiter

Release Build status codecov License

Client-side rate limiting for LLM API calls using Redis-backed FIFO queues.

Features

  • FIFO Queue-Based: Fair ordering prevents thundering herd problems
  • Distributed: Redis-backed for multi-process/multi-server deployments
  • Flexible Limits: Supports combined TPM, split input/output TPM, or both
  • Automatic Retry: Exponential backoff with jitter for Redis connection issues
  • Graceful Degradation: Allows requests through on Redis failure

How It Works

flowchart LR
    subgraph Client["Your Application"]
        App[LLM App]
    end

    subgraph RL["LLMRateLimiter"]
        Limiter[RateLimiter]
    end

    subgraph Redis["Redis"]
        Queue[(FIFO Queue<br/>Sorted Set)]
    end

    subgraph LLM["LLM Provider"]
        API[API]
    end

    App -->|1. acquire| Limiter
    Limiter -->|2. Check limits| Queue
    Queue -->|3. Wait time| Limiter
    Limiter -->|4. Return| App
    App -->|5. Call API| API

The rate limiter uses Redis sorted sets to maintain a FIFO queue of requests. Each request records its token consumption, and the Lua script atomically calculates when capacity will be available based on the sliding window.

Installation

pip install llmratelimiter

Or with uv:

uv add llmratelimiter

Quick Start

Basic Usage

from llmratelimiter import RateLimiter

# Just pass a Redis URL and your limits
limiter = RateLimiter("redis://localhost:6379", "gpt-4", tpm=100_000, rpm=100)

# Recommended: specify input and output tokens separately
await limiter.acquire(input_tokens=3000, output_tokens=2000)
response = await openai.chat.completions.create(...)

Split Mode (GCP Vertex AI)

For providers with separate input/output token limits:

limiter = RateLimiter(
    "redis://localhost:6379", "gemini-1.5-pro",
    input_tpm=4_000_000, output_tpm=128_000, rpm=360
)

# Estimate output tokens upfront
result = await limiter.acquire(input_tokens=5000, output_tokens=2048)
response = await vertex_ai.generate(...)

# Adjust after getting actual output
await limiter.adjust(result.record_id, actual_output=response.output_tokens)

AWS Bedrock (Burndown Rate)

AWS Bedrock uses a burndown rate where output tokens count 5x toward TPM:

limiter = RateLimiter(
    "redis://localhost:6379", "claude-sonnet",
    tpm=100_000, rpm=100, burndown_rate=5.0
)

await limiter.acquire(input_tokens=3000, output_tokens=1000)
# TPM consumption: 3000 + (5.0 * 1000) = 8000 tokens

Azure OpenAI (RPS Smoothing)

Azure OpenAI enforces rate limits at sub-second intervals. If you set 600 RPM, Azure actually enforces 10 requests per second. Bursts can trigger 429 errors even when you're under the minute-level limit.

Enable RPS smoothing to prevent burst-triggered rate limits:

# Auto-calculate RPS from RPM (600 RPM = 10 RPS = 100ms minimum gap)
limiter = RateLimiter(
    "redis://localhost:6379", "gpt-4",
    tpm=300_000, rpm=600, smooth_requests=True
)

# Or set explicit RPS for more conservative rate limiting
limiter = RateLimiter(
    "redis://localhost:6379", "gpt-4",
    tpm=300_000, rpm=600, rps=8  # 125ms minimum gap
)

# Custom evaluation interval (Azure may use 1s or 10s intervals)
limiter = RateLimiter(
    "redis://localhost:6379", "gpt-4",
    tpm=300_000, rpm=600, smooth_requests=True, smoothing_interval=10.0
)

With Existing Redis Client

from redis.asyncio import Redis
from llmratelimiter import RateLimiter

redis = Redis(host="localhost", port=6379)
limiter = RateLimiter(redis=redis, model="gpt-4", tpm=100_000, rpm=100)

await limiter.acquire(input_tokens=3000, output_tokens=2000)

With Connection Manager (Production)

For production use with automatic retry and connection pooling:

from llmratelimiter import RateLimiter, RedisConnectionManager, RetryConfig

manager = RedisConnectionManager(
    "redis://localhost:6379",
    retry_config=RetryConfig(max_retries=3, base_delay=0.1),
)
limiter = RateLimiter(manager, "gpt-4", tpm=100_000, rpm=100)

await limiter.acquire(input_tokens=3000, output_tokens=2000)

SSL Connection

Use rediss:// for SSL/TLS connections:

limiter = RateLimiter("rediss://localhost:6379", "gpt-4", tpm=100_000, rpm=100)

Configuration Options

RateLimitConfig

Parameter Description
tpm Combined tokens-per-minute limit
input_tpm Input tokens-per-minute limit
output_tpm Output tokens-per-minute limit
rpm Requests-per-minute limit
window_seconds Sliding window size (default: 60)
burst_multiplier Allow burst above limits (default: 1.0)
burndown_rate Output token multiplier for combined TPM (default: 1.0, AWS Bedrock: 5.0)
smooth_requests Enable RPS smoothing for burst prevention (default: True)
rps Explicit requests-per-second limit (auto-enables smoothing when > 0)
smoothing_interval Evaluation interval for RPS in seconds (default: 1.0)

RetryConfig

Parameter Description
max_retries Maximum retry attempts (default: 3)
base_delay Initial delay in seconds (default: 0.1)
max_delay Maximum delay cap (default: 5.0)
exponential_base Backoff multiplier (default: 2.0)
jitter Random variation 0-1 (default: 0.1)

License

MIT License - see LICENSE for details.

Release files for LLMRateLimiter 0.3.2

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

Source distribution (sdist)

Source distribution for LLMRateLimiter 0.3.2
File Size Uploaded
llmratelimiter-0.3.2.tar.gz 91.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for LLMRateLimiter 0.3.2
File Interpreter ABI Platform
llmratelimiter-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 109.1 kB

Release files / llmratelimiter-0.3.2.tar.gz

Download URL llmratelimiter-0.3.2.tar.gz
Size 91.6 kB
Tags Source
SHA-256 checksum
How to use checksums
81e2f0dab928b99f264a6053b58a05879d0e7ab0088f0c471d1e75f35da06c8d
BLAKE2b-256 checksum
How to use checksums
3367b79d8d4cfd6d93483efd01e7927298ccfdc6236de3e89f8a09f8019a33b8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 18, 2025.

Transparency log

Release files / llmratelimiter-0.3.2-py3-none-any.whl

Download URL llmratelimiter-0.3.2-py3-none-any.whl
Size 17.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0de3ffac569756d958287b092961fadc5c5aab9d42ad7c762800c52b2e4a6f0e
BLAKE2b-256 checksum
How to use checksums
208ecf70b564971541582b8a4e81649b5d4722d65edd36703ecce35c2dd4f63d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 18, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.2 This release

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.0.1

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