·3 min read

Serverless Rate Limiting

Andreas ThomasAndreas ThomasSoftware Engineer @Upstash

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!";

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"),
});

Closing words

If you have any questions, please reach out to us on GitHub or the channels below.

Follow us on Discord and Twitter.