Colibri is a simple HTTP service built in Rust that implements an in-memory data structure for rate-limiting services. Rate counts are stored in memory so that Colibri can respond quickly.
Note: Restarting a Colibri node will restart any rate-limit counts.
Colibri implements the Token Bucket algorithm for rate-limiting clients. Currently, all Colibri data structures are held in memory without persistence so that it can quickly respond to incoming requests.
Colibri can be run in single-node mode or in multi-node mode. In single-node mode each Colibri node will keep track of rate-limits individually without using any distributed properties. This strategy could potentially work behind a round-robin load balancer that fairly distributes traffic but it gets quickly confusing with interleaved client requests.
In multi-node mode Colibri functions as a distributed hash table, assigning responsibility for distinct client IDs to individual nodes using consistent hashing. This is experimental; for instance, it's not currently designed to work around network partitions or dynamic cluster resizing.
After cloning this repo, you can quickly launch Colibri using the provided justfile recipes:
# Start a single node on port 8000
❯ just run# Start a 3-node cluster on ports 8001, 8002, 8003
❯ just run-clusterThen test the rate limiting:
❯ curl -XPOST -i http://localhost:8002/rl/test-client
HTTP/1.1 200 OK
content-type: application/json
content-length: 50
{"client_id":"test-client","calls_remaining":999}
❯ curl -XPOST -i http://localhost:8001/rl/test-client
HTTP/1.1 200 OK
content-type: application/json
content-length: 50
{"client_id":"test-client","calls_remaining":998}Use just --list to see all available recipes:
just run- Single-node mode on port 8000just run-cluster- 3-node cluster for testing distributed featuresjust run-nodeN- Individual nodes (1, 2, 3) for custom cluster setupjust test-cluster- Automated testing of multi-node functionalityjust test- Run all unit and integration tests
Click here for a terminal demo.
The following configuration options are available for running Colibri:
Usage: colibri [OPTIONS]
Options:
      --listen-address <LISTEN_ADDRESS>
          IP Address to listen on [env: LISTEN_ADDRESS=] [default: 0.0.0.0]
      --listen-port <LISTEN_PORT>
          Port to bind Colibri server to [env: LISTEN_PORT=] [default: 8000]
      --rate-limit-max-calls-allowed <RATE_LIMIT_MAX_CALLS_ALLOWED>
          Max calls allowed per interval [env: RATE_LIMIT_MAX_CALLS_ALLOWED=] [default: 1000]
      --rate-limit-interval-seconds <RATE_LIMIT_INTERVAL_SECONDS>
          Interval in seconds to check limit [env: RATE_LIMIT_INTERVAL_SECONDS=] [default: 60]
      --topology <TOPOLOGY>
          Other node addresses in the cluster (e.g., http://node1:8000,http://node2:8000). If empty, runs in single-node mode. [env: TOPOLOGY=]
  -h, --help
          Print help$ cargo run# Run each in separate terminals
$ cargo run -- --listen-port 8001 --topology http://localhost:8002 --topology http://localhost:8003
$ cargo run -- --listen-port 8002 --topology http://localhost:8001 --topology http://localhost:8003
$ cargo run -- --listen-port 8003 --topology http://localhost:8001 --topology http://localhost:8002Note: The --topology flag specifies OTHER nodes in the cluster (not including the current node).