Rate limiting is an important mechanism for controlling resource utilization and maintaining quality of service. Elixir elegantly supports rate limiting with processes and messages.
Running our program we see the first batch of requests handled once every ~200 milliseconds as desired.
For the second batch of requests, we serve the first 3 immediately because of the burstable rate limiting, then serve the remaining 2 with ~200ms delays each.
This Elixir implementation uses GenServers to manage the state and timing of our rate limiters. The basic rate limiter processes one request every 200ms, while the bursty rate limiter allows for up to 3 requests to be processed immediately before falling back to the 200ms delay.
The RateLimiter module implements a simple rate limiter that processes one request every 200ms. The BurstyRateLimiter module implements a more complex rate limiter that allows for bursts of up to 3 requests, while still maintaining an overall rate limit.
In both cases, we’re using Elixir’s powerful concurrency primitives to manage the timing and state of our rate limiters. This approach allows us to handle rate limiting in a clean, functional way that’s idiomatic to Elixir.