ChallengeĀ¶
You recently developed a REST API that lets people fetch scores and details about š beach volleyball games. Unfortunately, some people are abusing the API, making hundreds of requests per second š¤!
In order to protect your servers, implement a sliding window API rate limiter that works like this..
- Each request to your API has an associated API key.
- Each API key is allowed to make up to 5 requests in any 10-second window.
Exclude denied requests from each key's quota. In other words, if a key makes a request every second for 60 seconds, 30 of its requests should be allowed (5 allowed, then 5 denied, then 5 allowed, then 5 denied, ...).
Starter Code
SolutionĀ¶
Stream
Tests
Explanation
This solution relies on a redis stream. Redis streams act like an append only log. Furthermore, we can restrict the size of a stream, and redis automatically tracks the time each stream entry gets added. š We can leverage these properties to implement our rate limiter with the following algorithm..
First, check if the stream exists. If it doesn't, allow the request and create the stream with its first entry. Initially it might look like this
Breakdown
1662818315896-0
is the auto-generated id of the entry.1662818315896
is the number of milliseconds since 1970-01-01 00:00:00 UTC.-0
is a sequential id, in case we happened to insert multiple elements within the same millisecond.
{'': ''}
is the key-value pair for this entry. (For our purposes, this data is not needed, so we use empty strings.)
As the user makes more requests, the stream continues to grow..
If we restrict the stream to a max size of 5, then each new stream element will push the oldest element out of the stream!
So, how do we impose the rate limit?
When a new API request comes in, we block the request if
- the stream has 5 elements and
- the oldest stream element was created less than 10 seconds ago.
Otherwise, we allow the request and insert a new entry into the stream.
Sorted Set
Tests
Explanation
This solution relies on a redis sorted set. Sorted sets let you store a collection of unique strings, each with an associated score which can be used to sort the collection's elements, fetch elements by range, remove elements by range, etc.
In our case, we create a sorted set for each API key. Each sorted set has one element per allowed API request. We set the name and score of each element as the Unix epoch time of the request (i.e. the number of seconds since 1970-01-01 00:00:00).
For example, the API key 123 might have a sorted set like this.
When a new request comes in, we remove elements from the sorted set which are more than 10 seconds old. Then we check the length of the sorted set. If the length is >= 5, we deny the request. Otherwise, we allow the request and insert a new element into the sorted set (representing the time of this new request).