{"id":9361,"library":"token-throttler","title":"Token Throttler","description":"Token throttler is an extendable rate-limiting library for Python, somewhat based on the token bucket algorithm. It supports both blocking (sync) and non-blocking (async) operations, global and instance-specific configurations, and various storage backends including in-memory and Redis. The current version is 1.5.1, actively maintained with regular updates.","status":"active","version":"1.5.1","language":"en","source_language":"en","source_url":"https://github.com/yuval-po/token-throttler","tags":["rate-limiting","token-bucket","throttling","concurrency","async"],"install":[{"cmd":"pip install token-throttler","lang":"bash","label":"Basic Installation"},{"cmd":"pip install token-throttler[redis]","lang":"bash","label":"With Redis Storage"}],"dependencies":[{"reason":"Requires Python >=3.8, <4.0","package":"python","optional":false},{"reason":"Optional storage backend for distributed throttling","package":"redis","optional":true}],"imports":[{"symbol":"TokenThrottler","correct":"from token_throttler import TokenThrottler"},{"symbol":"TokenThrottlerAsync","correct":"from token_throttler import TokenThrottlerAsync"},{"symbol":"TokenBucket","correct":"from token_throttler import TokenBucket"},{"symbol":"ThrottlerConfig","correct":"from token_throttler import ThrottlerConfig"},{"note":"Singleton global configuration object.","symbol":"default_config","correct":"from token_throttler import default_config"},{"note":"In-memory storage for TokenThrottler.","symbol":"RuntimeStorage","correct":"from token_throttler.storage import RuntimeStorage"}],"quickstart":{"code":"from token_throttler import TokenBucket, TokenThrottler\nfrom token_throttler.storage import RuntimeStorage\n\n# Initialize a throttler with a default cost of 1 token per consumption\n# and in-memory storage.\nthrottler: TokenThrottler = TokenThrottler(cost=1, storage=RuntimeStorage())\n\n# Add a token bucket named 'api_limit'\n# It can hold 10 tokens and replenishes 10 tokens every 60 seconds (1 token per 6s).\nthrottler.add_bucket(\n    identifier=\"api_limit\",\n    bucket=TokenBucket(replenish_time=60, max_tokens=10)\n)\n\ndef make_api_call():\n    if throttler.consume(\"api_limit\"):\n        print(\"API call allowed. Remaining tokens for 'api_limit'.\")\n        # Simulate actual API call\n    else:\n        print(\"API call denied. Rate limit exceeded for 'api_limit'.\")\n\nfor i in range(15):\n    print(f\"Attempt {i+1}: \", end=\"\")\n    make_api_call()\n\n# Example of using a specific cost for consumption\nthrottler.add_bucket(\"heavy_operation\", TokenBucket(replenish_time=30, max_tokens=5))\nif throttler.consume(\"heavy_operation\", cost=2):\n    print(\"Heavy operation allowed (cost 2 tokens).\")\nelse:\n    print(\"Heavy operation denied (cost 2 tokens).\")","lang":"python","description":"This quickstart demonstrates initializing `TokenThrottler` with `RuntimeStorage` and adding a basic `TokenBucket`. It then simulates several API calls, showing how to consume tokens and handle rate limits. It also includes an example of consuming tokens with a custom cost."},"warnings":[{"fix":"Configure global settings using `default_config.set()` *before* initializing any `TokenThrottler` instances. For instance-specific overrides, pass a `ThrottlerConfig` object to the `TokenThrottler` constructor instead.","message":"Modifying the `default_config` (global configuration) object at runtime is not recommended and emits a `RuntimeWarning`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Set `ENABLE_THREAD_LOCK=True` in your `ThrottlerConfig` (globally or per instance) to enable a thread lock for the `consume` method, preventing race conditions. Be aware this incurs a slight performance cost.","message":"In multi-threaded applications, race conditions can occur. The library offers `ENABLE_THREAD_LOCK` to mitigate this.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure all identifiers used in `consume` have a corresponding `TokenBucket` added via `throttler.add_bucket()`. Alternatively, set `IDENTIFIER_FAIL_SAFE=True` in `ThrottlerConfig` to make unknown identifiers act as limitless buckets, preventing `KeyError`.","message":"Calling `throttler.consume()` with an unknown `identifier` will raise a `KeyError` by default.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Before calling `throttler.consume('my_id')`, ensure you've called `throttler.add_bucket('my_id', TokenBucket(max_tokens=X, replenish_time=Y))` or set `IDENTIFIER_FAIL_SAFE=True` in the throttler's `ThrottlerConfig`.","cause":"Attempted to consume tokens for an identifier that has no associated token bucket, and `IDENTIFIER_FAIL_SAFE` is set to `False` (the default).","error":"KeyError: 'Bucket for identifier 'my_id' not found'"},{"fix":"Perform all modifications to `default_config` at the very start of your application, before any `TokenThrottler` instances are initialized. For dynamic configuration, use instance-specific `ThrottlerConfig` objects when creating `TokenThrottler` instances.","cause":"The global `default_config` singleton was modified after `TokenThrottler` instances that rely on it were already created. This can lead to unpredictable throttling behavior.","error":"RuntimeWarning: Modifications on default_config object during runtime are not recommended"},{"fix":"Review your `TokenBucket` configurations. `max_tokens` determines burst capacity, `replenish_time` determines the rate at which tokens are refilled. Also, check the `cost` parameter in `consume()` calls. For multi-threaded scenarios, consider enabling `ENABLE_THREAD_LOCK=True` in your `ThrottlerConfig` to prevent token overconsumption due to race conditions.","cause":"The `TokenBucket` parameters (`max_tokens`, `replenish_time`) or the `cost` specified in `throttler.consume()` are not correctly configured for the desired rate limit, or not considering concurrent access without `ENABLE_THREAD_LOCK`.","error":"My application is unexpectedly hitting rate limits (429 errors) or not throttling correctly."}]}