·2 min read

Rate Limiting Next.js API Routes using Upstash Redis

Noah FischerNoah FischerSoftware Engineer, Guest Author

In this article, we will show how to rate limit your Next.js API routes using the Upstash Rate limit SDK

Database Setup

Create a Redis database using Upstash Console or Upstash CLI. Copy the UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN for the next steps.

Project Setup

We will create a Next.js application and deploy to Vercel.

npx create-next-app@latest

Install @upstash/ratelimit:

npm install @upstash/ratelimit @upstash/redis

The Code

Update your pages/api/hello.js as below and replace UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN.

import {Ratelimit} from "@upstash/ratelimit";
import {Redis} from "@upstash/redis";
 
 
const redis = new Redis({
  url: 'UPSTASH_REDIS_REST_URL',
  token: 'UPSTASH_REDIS_REST_TOKEN',
})
 
// Create a new ratelimiter, that allows 5 requests per 5 seconds
const ratelimit = new Ratelimit({
  redis: redis,
  limiter: Ratelimit.fixedWindow(5, "5 s"),
});
 
export default async function handler(req, res) {
// 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 result = await ratelimit.limit(identifier);
  res.setHeader('X-RateLimit-Limit', result.limit)
  res.setHeader('X-RateLimit-Remaining', result.remaining)
 
  if (!result.success) {
    res.status(200).json({message: 'The request has been rate limited.', rateLimitState: result})
    return
  }
 
  res.status(200).json({name: 'John Doe', rateLimitState: result})
}

Here, we allow 5 requests per 5 seconds.

Run

Run the app with npm run dev. Refresh the browser more than 5 times and you will see the rate limiting in action.

{"message":"The request has been rate limited.","rateLimitState":{"success":false,"limit":5,"remaining":-1,"reset":1654546770000,"pending":{}}}

Possible Enhancements

  • Use your user's id or IP address as identifier to limit the usage per user.
const identifier = getClientIp(req);
const result = await ratelimit.limit(identifier);
const ratelimit = new Ratelimit({
  redis: redis,
  limiter: Ratelimit.slidingWindow(10, "10 s"),
});
const ratelimit = new Ratelimit({
  redis: redis,
  limiter: Ratelimit.tokenBucket(5, "10 s", 10),
});
  • Use multiple Redis in different regions if your Next.js application is deployed to different regions. This will help you to minimize latency for different locations.

  • Keep and read your Upstash Redis credentials from environment variables or secret store.