bottleneck icon indicating copy to clipboard operation
bottleneck copied to clipboard

Support rate limiting with sliding window log algorithm

Open stansv opened this issue 5 years ago • 2 comments

As far as I know the sliding window log technique gives the best accuracy having only one disadvantage in relatively high memory consumption, which is OK for API clients. We consume API with strict limits: 60 requests per one-minute window and 5000 per 24-hour window. Exceeding these limits is very undesirable since each new attempt will be counted by server and fail, extending the time we cannot use API.

Do you have any plans to support such functionality? Looks like this can be accomplished with ZREMRANGEBYSCORE (https://engineering.classdojo.com/blog/2015/02/06/rolling-rate-limiter/). There's also some NodeJS implementation referenced from this article but looks like it doesn't support delayed execution as like in your library.

stansv avatar Jun 25 '19 07:06 stansv

Thank you for the ticket, was just looking to implement something like this. Currently trying to wrap Hubspot's API calls. Hubspot uses a window limit instead of a hard limit like stripe.

UnbrandedTech avatar Nov 11 '19 20:11 UnbrandedTech

@stansv how about chaining the limiters?

const limiterPerDay = new Bottleneck({
  reservoir: 5000,
  reservoirRefreshAmount: 5000,
  reservoirRefreshInterval: 24 * 60 * 60 * 1000, // must be divisible by 250
});
const limiterPerMinute = new Bottleneck({
  reservoir: 60,
  reservoirRefreshAmount: 60,
  reservoirRefreshInterval: 60 * 1000, // must be divisible by 250
});
limiterPerMinute.chain(limiterPerDay);

limiterPerMinute.schedule(() => {...});

To handle out of limit errors you can use the following code:



limiterPerMinute.on('failed', (error, jobInfo) => {
  const isOutOfLimits = ...;

  if (isOutOfLimits) {
    limiterPerMinute.incrementReservoir(-Infinity);

    return 60 * 1000;
  }
});

SleepWalker avatar Nov 28 '19 15:11 SleepWalker