Control how many tasks run at once and how fast they start. Use it when you're calling an API that has rate limits, or when you want to avoid overloading a service.
In production Node usually runs on multiple instances (containers, PM2 cluster, several servers). Each process has its own memory, so you need a Redis-backed limiter to share one limit across all of them. Use DistributedRateLimiter for that.
Install
npm install rate-queueDocs — Full guides and API reference: docs.page/taukirsheikh/rate-queue
Production (multiple instances) — use Redis
import { DistributedRateLimiter } from 'rate-queue';
const limiter = new DistributedRateLimiter({
maxConcurrent: 10,
redis: { url: process.env.REDIS_URL || 'redis://localhost:6379' },
});
await limiter.ready();
const result = await limiter.schedule(() => fetch('https://api.example.com/data'));All instances share the same queue and limits. If Redis is down, see the docs for waiting until Redis is back (recommended with multiple instances) vs falling back to in-memory (risky with multiple instances).
Single process (dev or one instance) — in-memory
import { RateLimiter } from 'rate-queue';
const limiter = new RateLimiter({
maxConcurrent: 2,
minTime: 500,
});
const result = await limiter.schedule(() => fetch('https://api.example.com/data'));Sample: API function + limiter.schedule
Define an async function that calls your API, then run it through the limiter so it’s rate-limited:
import { DistributedRateLimiter } from 'rate-queue';
// Your API-calling function
async function fetchUser(id) {
const res = await fetch(`https://api.example.com/users/${id}`);
if (!res.ok) throw new Error(res.statusText);
return res.json();
}
const limiter = new DistributedRateLimiter({
maxConcurrent: 5,
redis: { url: process.env.REDIS_URL || 'redis://localhost:6379' },
});
await limiter.ready();
// Run the function through the limiter — same args, same return
const user = await limiter.schedule(() => fetchUser(1));schedule returns whatever your function returns, so you can destructure:
// With axios
const { data } = await limiter.schedule(async () => axios.request(config));
// Or wrap once and call many times
const limitedFetchUser = limiter.wrap(fetchUser);
const user1 = await limitedFetchUser(1);
const user2 = await limitedFetchUser(2);What you can do
- Limit concurrency (e.g. max 5 at a time).
- Space out jobs (e.g. at least 100ms between starts).
- Cap jobs per minute/hour with
maxPerIntervalandinterval. - Use a token bucket with
reservoirand refill options. - Give jobs priority so important work runs first.
- Wrap any async function with
limiter.wrap(fn). - Retry failed jobs with
retryCountandretryDelay. - Cancel with
limiter.cancel(jobId)or anAbortSignal.
Try the examples
npm run example # in-memory limiter
npm run example:redis # Redis (needs Redis running)License — MIT