Rate Limiting Calls to External API with Node.js
We’ve all been there; testing external API calls without paying attention to the service’s rate limits and… BAM! We get hit by Status Code 429.
Today, we’ll go over a very simple algorithm, to prevent that from happening. The following is a simplified version of the “leaky bucket algorithm,” modified to leverage the async/await paradigm.
A leaky bucket boils down to this: we enqueue requests, and the bucket executes them at a regular interval to ensure we never hit a rate limit. We’ll write a simple implementation below.
Here, we are simply defining the wrapper we’ll use to make API calls.
The method takes a URL (endpoint), optional method (default is GET), and optional request body.
The meat of this method looks intimidating, but it’s quite simple.
We make a new Promise, which will not return until the leaky bucket (LB) succeeds or fails.
We do this by forwarding the request to LB_QueueApiCall
with the payload defined above, and wrapping the aforementioned Promise’s resolve
and reject
methods in a local callback (err, _data) => { ... };
The implementation of our leaky bucket will be via a simple queue. As a reminder, queues are a FIFO (first in; first out) data structure.
The idea is to dequeue the next request every interval tick. The interval is defined by the external’s API rate limit.
Connecting it all together is the method LB_QueueApiCall
which, as we mentioned, takes a request payload, and a callback which will resolve the awaiting promise.
If there are no requests queued, the interval is cleared to free up resources.
On the other hand, if we are queuing requests for the first time in a while, we start a new interval.
And that’s it! From now on, you should be making external calls using MakeApiCall(url, method, body)
instead of directly calling axios, fetch, etc… and you’ll never have to deal with HTTP 429 again!