how can control rate limit in next js 14

418 Views Asked by At

I am using Next Js 14 and Mongo DB.

In Node Js, we can use Express Rate Limit package to control website users requests number. if a user requests to the website more 200 times in 15 minutes, the package block that user for 15 minutes.

how can I do this work in Next Js 14 App router? thanks for your responses

1

There are 1 best solutions below

2
Yilmaz On

Using @upstash/ratelimit which is recommended by next.js docs

import { Ratelimit } from "@upstash/ratelimit";
import { kv } from '@vercel/kv'

const { limit } = new Ratelimit({
     redis: kv,
     limiter: Ratelimit.slidingWindow(
        // 200 requests from the same IP in 900 seconds
limiter: Ratelimit.slidingWindow(200, '900 s'),
    )
  })

You somehow keep track of each user, because you allow each user 200 requests. Vercel KV is a durable Redis database that enables you to store and retrieve simple key-value data structures globally at the edge.

If you do not want to use third party packages, you can follow this rate-limiting-serverless-functions

import { NextRequest, NextResponse } from 'next/server';

const idToRequestCount = new Map<string, number>(); // keeps track of individual users
const rateLimiter = {
  windowStart: Date.now(),
  windowSize: 10000,
  maxRequests: 10,
};

const limit = (ip: string) => {
  // Check and update current window
  const now = Date.now();
  const isNewWindow = now - rateLimiter.windowStart > rateLimiter.windowSize;
  if (isNewWindow) {
    rateLimiter.windowStart = now;
    idToRequestCount.set(ip, 0);
  }

  // Check and update current request limits
  const currentRequestCount = idToRequestCount.get(ip) ?? 0;
  if (currentRequestCount >= rateLimiter.maxRequests) return true;
  idToRequestCount.set(ip, currentRequestCount + 1);

  return false;
};

export async function GET(req: NextRequest) {
  const ip = req.ip ?? req.headers.get('X-Forwarded-For') ?? 'unknown';
  const isRateLimited = limit(ip);

  if (isRateLimited)
    return NextResponse.json({ error: 'rate limited' }, { status: 429 });

  return NextResponse.json({ data: 'success' }, { status: 200 });
}

It uses a Sliding Window Technique:

Instead of a fixed time window, we can track the number of requests within a moving time window, providing a dynamic approach by continuously updating the window.