LogoStarterkitpro
Security

Rate Limiting with Upstash

Protect your Next.js application from abuse by implementing rate limiting using Upstash Redis.

Rate limiting is a crucial security measure to prevent abuse of your API routes, server actions, and other resources. It restricts the number of requests a user (identified typically by IP address) can make within a specific time window. This helps mitigate brute-force attacks, denial-of-service (DoS) attempts, and excessive resource consumption.

We recommend using Upstash Redis along with the @upstash/ratelimit library for a robust and easy-to-implement solution.

Setup

  1. Create an Upstash Redis Database:

    • Sign up for a free account at Upstash.
    • Create a new Redis database. Choose a region close to your deployment server (e.g., Vercel).
    • Copy your UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN.
  2. Set Environment Variables: Add the Upstash credentials to your project's environment variables (.env.local for development, and your hosting provider's settings for production).

    .env.local
    UPSTASH_REDIS_REST_URL="YOUR_UPSTASH_REDIS_REST_URL"
    UPSTASH_REDIS_REST_TOKEN="YOUR_UPSTASH_REDIS_REST_TOKEN"
  3. Install Dependencies:

    Terminal
    npm install @upstash/ratelimit @upstash/redis

Implementation

You can apply the rate limiter directly inside your API Routes or Server Actions.

Apply Rate Limiting

You can apply the rate limiter in various parts of your Next.js application:

Apply rate limiting only to specific API routes using the matcher config in your middleware.

import { NextRequest, NextResponse } from "next/server";
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
 
// Initialize Redis client and Rate Limiter
// Ensure UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN are set
const redis = Redis.fromEnv();
const specificApiLimiter = new Ratelimit({
  redis: redis,
  limiter: Ratelimit.slidingWindow(3, "60 s"), // 3 requests per 60 seconds
  analytics: true,
  prefix: "@upstash/ratelimit/middleware/specific", // Unique prefix
});
 
export default async function middleware(request: NextRequest) {
  // Rate limit is applied only to paths defined in the matcher below
  const ip = request.ip ?? "127.0.0.1"; // Get IP from request
  const { success, limit, remaining, reset } =
    await specificApiLimiter.limit(ip);
 
  if (!success) {
    console.log(
      `Rate limit exceeded for IP: ${ip} on specific path: ${request.nextUrl.pathname}`
    );
    // Redirect to a blocked page if the limit is exceeded
    return NextResponse.redirect(new URL("/blocked", request.url));
  }
 
  // Proceed if limit is not exceeded
  const res = NextResponse.next();
  // Optional: Add rate limit headers to the response even on success
  // const responseHeaders = {
  //   "X-RateLimit-Limit": limit.toString(),
  //   "X-RateLimit-Remaining": remaining.toString(),
  //   "X-RateLimit-Reset": reset.toString(),
  // };
  // res.headers.set('X-RateLimit-Limit', limit.toString());
  // res.headers.set('X-RateLimit-Remaining', remaining.toString());
  // res.headers.set('X-RateLimit-Reset', reset.toString());
  return res;
}
 
// Apply this middleware ONLY to specific API routes
export const config = {
  // Add the specific API paths you want to rate limit here
  matcher: ["/api/important-resource", "/api/sensitive-data"],
};

Rate Limit Configuration

Adjust the slidingWindow(requests, duration) parameters (e.g., slidingWindow(5, "60 s")) based on expected traffic and the sensitivity of the resource being protected. Monitor Upstash analytics to fine-tune your limits.

By implementing rate limiting with Upstash, you add a significant layer of protection to your Next.js application against various forms of abuse. Remember to choose the appropriate implementation method and configure your limits thoughtfully.

Blocked Page

Create Blocked Page

Remember to create a simple page at app/blocked/page.tsx to inform users that they have been rate-limited. You can create the page by following the Blocked Page guide.

On this page