Maintaining your system's availability is one of the most critical tasks for any product. Unfortunately, people might abuse it by overwhelming your resources, or you want to limit the usage and charge for it. Rate limiting is a standard solution to many of these problems and should work out of the box. After all, you have already built your system and don't want to spend even more time designing a rate-limiting system that works well in a stateless environment such as serverless functions.
Announcing @upstash/ratelimit
Available on GitHub, npm or Deno
Today we are releasing @upstash/ratelimit
, a solution for rate-limiting in serverless environments, such as Vercel, Cloudflare, Deno, Fastly and Netlify. It is built on top of Upstash Serverless Redis and provides rate-limiting solutions using one or more databases to offer a low latency experience for your users worldwide!
Get started
@upstash/ratelimit
implements three different standardized algorithms so far, and you can read more about them in the project's README.
We provide two methods:
limit(identifier: string): Promise<RatelimitResponse>
limit
will return true
or false
and some metadata about remaining requests and can be used if you want to reject all requests beyond your set limit.
blockUntilReady(identifier: string, timeout: number): Promise<RatelimitResponse>
In case you don't want to reject a request immediately but wait until it can be processed. Keep in mind that some platforms charge you for the execution time of your function.
Single regional database
Ratelimiting with a single database is straight forward. You create a database on Upstash and start using it:
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
// Create a new ratelimiter, that allows 10 requests per 10 seconds
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, "10 s"),
});
// Use a constant string to limit all requests with a single ratelimit
// Or use a userID, apiKey or ip address for individual limits.
const identifier = "api";
const { success } = await ratelimit.limit(identifier);
if (!success) {
return "Unable to process at this time";
}
doExpensiveCalculation();
return "Here you go!";
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
// Create a new ratelimiter, that allows 10 requests per 10 seconds
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, "10 s"),
});
// Use a constant string to limit all requests with a single ratelimit
// Or use a userID, apiKey or ip address for individual limits.
const identifier = "api";
const { success } = await ratelimit.limit(identifier);
if (!success) {
return "Unable to process at this time";
}
doExpensiveCalculation();
return "Here you go!";
Global replicated rate-limiting
Let's assume you have customers in the US and Europe. In this case, you can create two regional redis databases on Upstash and your users will enjoy the latency of whichever db is closest to them.
import { GlobalRatelimit } from "@upstash/ratelimit"; // for deno: see above
import { Redis } from "@upstash/redis";
// Create a new ratelimiter, that allows 10 requests per 10 seconds
const ratelimit = new GlobalRatelimit({
redis: [
new Redis({
/* europe */
}),
new Redis({
/* north america */
}),
],
limiter: Ratelimit.slidingWindow(10, "10 s"),
});
import { GlobalRatelimit } from "@upstash/ratelimit"; // for deno: see above
import { Redis } from "@upstash/redis";
// Create a new ratelimiter, that allows 10 requests per 10 seconds
const ratelimit = new GlobalRatelimit({
redis: [
new Redis({
/* europe */
}),
new Redis({
/* north america */
}),
],
limiter: Ratelimit.slidingWindow(10, "10 s"),
});
Closing words
If you have any questions, please reach out to us on GitHub or the channels below.