{"id":43810670,"url":"https://github.com/maciejgz/python-rate-limiter","last_synced_at":"2026-02-05T23:30:29.256Z","repository":{"id":239477277,"uuid":"799626848","full_name":"maciejgz/python-rate-limiter","owner":"maciejgz","description":"Rate limiting algorithms implementation with Python","archived":false,"fork":false,"pushed_at":"2025-05-11T16:06:43.000Z","size":46,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-11T17:23:15.331Z","etag":null,"topics":["fastapi","python","rate-limiter","rate-limiting","system-design"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maciejgz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-05-12T17:42:31.000Z","updated_at":"2025-05-11T16:06:46.000Z","dependencies_parsed_at":"2024-05-21T21:30:09.464Z","dependency_job_id":"af0a4167-384e-40f9-9abb-4afab69d56e1","html_url":"https://github.com/maciejgz/python-rate-limiter","commit_stats":null,"previous_names":["maciejgz/python-rate-limiter"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/maciejgz/python-rate-limiter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maciejgz%2Fpython-rate-limiter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maciejgz%2Fpython-rate-limiter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maciejgz%2Fpython-rate-limiter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maciejgz%2Fpython-rate-limiter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maciejgz","download_url":"https://codeload.github.com/maciejgz/python-rate-limiter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maciejgz%2Fpython-rate-limiter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29138375,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T23:14:48.546Z","status":"ssl_error","status_checked_at":"2026-02-05T23:14:35.724Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","python","rate-limiter","rate-limiting","system-design"],"created_at":"2026-02-05T23:30:28.071Z","updated_at":"2026-02-05T23:30:29.249Z","avatar_url":"https://github.com/maciejgz.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# python-rate-limiter\n\n## Description\n\nPlayground for analyzing the ways to limit the rate of API calls in Python. The main goal is to create a simple and efficient rate limiter that can be used in any Python project and to test different approaches to rate limiting.\nFor test purposes simple API writtern with fastapi ([FastAPI](https://fastapi.tiangolo.com/)).\n\n## Algorithms\n\n### Rate limiting\nRate limiting is a technique used to control the rate of traffic sent or received by a network. It is used to prevent abuse of the network and to ensure that the network is used in a fair way. Rate limiting can be used to prevent denial of service attacks, to prevent spam, and to ensure that the network is used in a fair way.\n\n#### Token bucket algorithm\nThe token bucket algorithm is a rate limiting algorithm that is used to control the rate of traffic sent or received by a network. It is used to prevent abuse of the network and to ensure that the network is used in a fair way. The token bucket algorithm works by maintaining a bucket of tokens. Each token represents a unit of traffic that can be sent or received by the network. When a packet of traffic is sent or received by the network, a token is removed from the bucket. If the bucket is empty, the packet is dropped or delayed until a token becomes available. The token bucket algorithm is a simple and efficient way to control the rate of traffic sent or received by a network. Token bucket algorithm is implemented in two ways:\n- in_memory_token_bucket - [source code](/src/in_memory_token_bucket.py) - single instance of token bucket. Each user can make one request per 15 seconds. Rate limit is set to 100 requests per 15 seconds. Tokens are refilled every 15 seconds.\n- redis_token_bucket - [source code](/src/redis_token_bucket.py) - distributed token bucket. Each user can make one request per 15 seconds. Rate limit is set to 100 requests per 15 seconds. Redis is used to store the state of the token bucket. Only one instance of the rate limiter instance is responsible for refilling the tokens. The other instances of the rate limiter instance are responsible for consuming the tokens. The token bucket algorithm is a simple and efficient way to control the rate of traffic sent or received by a network.\n\nToken bucket algorithm requires a single instance of the rate limiter to be responsible for refilling the tokens. This is done by setting the `MASTER_NODE` environment variable to `True`. The other instances of the rate limiter are responsible for consuming the tokens. The token bucket algorithm is a simple and efficient way to control the rate of traffic sent or received by a network.\n\n#### Sliding window algorithm\nThe sliding window algorithm ([source code](/src/sliding_window.py)) is a rate limiting algorithm that is used to control the rate of traffic sent or received by a network. It is used to prevent abuse of the network and to ensure that the network is used in a fair way. The sliding window algorithm works by maintaining a window of tokens. Each token represents a unit of traffic that can be sent or received by the network. When a packet of traffic is sent or received by the network, a token is removed from the window. If the window is empty, the packet is dropped or delayed until a token becomes available. The sliding window algorithm is a simple and efficient way to control the rate of traffic sent or received by a network.\n##### Redis sliding window\n- Redis sorted set is used to store the state of the sliding window. Rate limit is set to 5 requests per 5 seconds - [Redis sorted set](https://redis.io/docs/latest/develop/data-types/sorted-sets/)\n- To add a new request to the sliding window, the timestamp of the request is added to the sorted set as a score. The score is the timestamp of the request. The value is a unique identifier of the request.\n- Redis commands used in the sliding window algorithm:\n    - ZADD - adds a new request to the sliding window\n    - ZRANGEBYSCORE - gets all requests from the sliding window that are within the rate limit\n    - ZCARD - gets the number of requests in the sliding window\n\n#### Leaking bucket algorithm - #TODO - implement leaking bucket algorithm with some queue\nThe leaking bucket algorithm is a rate limiting algorithm that is used to control the rate of traffic sent or received by a network. It is used to prevent abuse of the network and to ensure that the network is used in a fair way. The leaking bucket algorithm works by maintaining a bucket of tokens represented by the queue. Each token represents a unit of traffic that can be sent or received by the network. When a packet of traffic is sent or received by the network, a token is removed from the queue. If the queue is full, the packet is dropped or delayed until a token becomes available. The leaking bucket algorithm is a simple and efficient way to control the rate of traffic sent or received by a network. The leaking bucket algorithm is implemented in two ways:\n- leaking_bucket_queue - [source code](/src/leaking_bucket_queue.py) - single instance of leaking bucket. Each user can make one request per 15 seconds. Rate limit is set to 100 requests per 15 seconds. Tokens are refilled every 15 seconds.\n\n## Configuration\n\nThe rate limiter can be configured by setting the following environment variables:\n- `RATE_LIMITER_ALGORITHM` - the rate limiting algorithm to use. Available options are:\n    - in_memory_token_bucket\n    - redis_token_bucket\n    - sliding_window\n    - leaking_bucket_queue\n\n## Installation\n\nTo install the dependencies, run the following command:\n\n```bash\npip install -r requirements.txt\n```\n\n## Usage\n\n## Pre-requisites\n###  Run Redis\n\n```bash\ndocker-compose -f docker/redis.yml up -d \n```\nThis command will start a Redis container and create a network called `docker_python-rate-limiter-network` which will be used by the rate limiter container to connect to Redis.\n\nThen you can connect to Redis using the following command:\n```bash\n docker exec -it python-rate-limiter-redis redis-cli\n```\n\n### Run ActiveMQ\n```bash\ndocker-compose -f docker/activemq.yml up -d \n```\n\n\n## Run rate limiter locally\nTo run rate-limiter locally. Params:\n- `MASTER_NODE` - if set to `True` the instance will be responsible for refilling the tokens. Default is `False`. Required for `redis_token_bucket` algorithm.\n- `RATE_LIMITER_ALGORITHM` - the rate limiting algorithm to use. Default is `in_memory_token_bucket`. Allowed values are `in_memory_token_bucket`, `redis_token_bucket`, `sliding_window`\n- `--port` - port on which the API will be available. Default is `8000`\n\n### in_memory_token_bucket\nSingle instance of token bucket. Each user can make one request per 15 seconds. Tokens are refilled every 15 seconds.\n```bash\n$env:RATE_LIMITER_ALGORITHM=\"in_memory_token_bucket\"; $env:MASTER_NODE=\"True\"; fastapi run main.py --port 8000\n```\n\n### redis_token_bucket\nDistributed token bucket which requires a Redis instance to be running. Each user can make one request per 15 seconds. Rate limit is set to 100 requests per 15 seconds. Only one instance of the rate limiter instance is responsible for refilling the tokens. The other instances of the rate limiter instance are responsible for consuming the tokens.\nTo run the rate limiter as a master node, run the following command:\n```bash\n$env:RATE_LIMITER_ALGORITHM=\"redis_token_bucket\"; $env:MASTER_NODE=\"True\"; $env:REDIS_HOST=\"localhost\"; fastapi run main.py --port 8000\n```\n\nTo run the rate limiter as a slave node, run the following command:\n```bash\n$env:RATE_LIMITER_ALGORITHM=\"redis_token_bucket\"; $env:MASTER_NODE=\"False\"; $env:REDIS_HOST=\"localhost\"; fastapi run main.py --port 8001\n```\n\n### sliding_window\nDistributed sliding window algorithm which requires a Redis instance to be running. Each user can make one request per 5 seconds. Rate limit is set to 5 requests per 5 seconds for all users.\nYou can run mulltiple instances of the rate limiter. There is no need to set the `MASTER_NODE` environment variable. The rate limiter will automatically use the Redis instance to store the state of the sliding window.\n```bash\n$env:RATE_LIMITER_ALGORITHM=\"sliding_window\"; $env:REDIS_HOST=\"localhost\"; fastapi run main.py --port 8000\n```\n\n### leaking_bucket_queue\nDistributed leaking bucket algorithm which requires a queue to be running. Each user can make one request per 15 seconds. Rate limit is set to 5 requests and one request is consumed every 5 seconds.\n```bash\n$env:RATE_LIMITER_ALGORITHM=\"leaking_bucket_queue\"; $env:ACTIVEMQ_HOST=\"localhost\"; fastapi run main.py --port 8000\n```\n\n\n### Limitations and Additional Notes\n\n- The `in_memory_token_bucket` algorithm is **not distributed**. It only works within a single application instance. For distributed rate limiting, use the `redis_token_bucket`, `sliding_window` or `leaking_bucket_queue` algorithms.\n- The `redis_token_bucket` and `sliding_window` algorithm requires a Redis instance to be running. Make sure to set the `REDIS_HOST` environment variable to the hostname of the Redis instance.\n- Make sure to set `MASTER_NODE=True` only for one instance when using the `redis_token_bucket` algorithm to avoid race conditions during token refilling.\n- `MASTER_NODE` is not required for `sliding_window`, `in_memory_token_bucket` and 'leaking_bucket_queue' algorithms.\n- The `leaking_bucket_queue` algorithm requires a queue to be running. Make sure to set the `ACTIVEMQ_HOST` and `ACTIVEMQ_PORT` environment variables to the hostname of the queue instance.\n\n## Docker\nYou can build and run the rate limiter in a Docker container or deploy it to Kubernetes.\n\n### Build the image\nBuild the image used to run the rate limiter:\n```bash\ndocker build -t python-rate-limiter:latest .\n```\n\n### Run single container\nRun the rate limiter in a single container:\n```bash\ndocker run --network docker_python-rate-limiter-network -p 8000:8000 -e \"REDIS_HOST=python-rate-limiter-redis\" -e \"MASTER_NODE=True\" -e \"RATE_LIMITER_ALGORITHM=redis_token_bucket\" python-rate-limiter:latest\n```\n\n### Kubernetes\nPredefined Kubernetes deployment files are available in the `k8s` directory. It contains configuration with predefined algorithm and master/slave instances. \nTo deploy the rate limiter to Kubernetes, run the following command:\n```bash\nkubectl apply -f k8s/python-rate-limiter.yml\n```\nAPI will be available on port 80: http://localhost:80/\n\n## Testing\nThere is no API Gateway or load balancer in front of the API. The API is exposed directly to the internet. This is not recommended for production use. To test the API, you should call the service/services directly. The main goal is to test the rate limiting algorithms in a distributed environment.\nTo test the API, you can use the following command:\n```bash\ncurl -X GET http://localhost:8000\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaciejgz%2Fpython-rate-limiter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaciejgz%2Fpython-rate-limiter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaciejgz%2Fpython-rate-limiter/lists"}