site logo

Stacknatic

Stacknatic logo

We Care About Your Privacy

Stacknatic utilizes technologies, such as cookies, to enhance your browsing experience. By using this technology, you can be provided with a more personalized and seamless interaction with this website. By continuing, you agree with the Privacy Policy of Stacknatic.

Privacy Policy | Terms of Use
Home/blog/How to apply rate limit to Next.js App router

How to apply rate limit to Next.js App router

featured image for How to apply rate limit to Next.js App router

Published on: February 5, 2024 (Updated on: June 22, 2025)

Table of Contents

  • What is rate limit in API context?
  • Why use rate-limiting for your API?
  • What is Redis?How to install Redis

In this article, I am going to show you how to control access to an API resource in Next.js 13 and 14 using the App router. The technique I am going to demonstrate involves using Redis on your own server for rate limiting. This is a useful alternative to Vercel kv if your Next.js app is self-hosted. Similar posts available on this topic are based on the Next.js Page router, so I thought creating this post would be beneficial for those using the new Next.js app router.

To use Redis for rate-limiting in the Next.js App router, you need to have Redis installed on your server. You should probably use a VPS or similar hosting that grants you root access, as some shared hosting services do not offer Redis on their servers. If you're not familiar with Redis, don't worry; it's quite easy to install.

What is rate limit in API context?

Rate-limiting, sometimes referred to as throttling, can help prevent abuse, protect against denial-of-service (DoS) attacks, and ensure fair usage of server resources. It involves restricting the number of requests made to a server or API within a defined period. Rate-limiting sets thresholds on the frequency of requests, typically measured in requests per second (RPS) or requests per minute (RPM). When the limit is reached, further requests may be delayed, rejected, or handled differently based on the rate-limiting strategy in place.

Why use rate-limiting for your API?

Implementing rate-limiting for your API offers several benefits:

  • Prevent Abuse: Limiting requests discourages spamming, scraping, or unauthorized access.
  • Protect Server Resources: Controls incoming requests to prevent server overload.
  • Ensure Fair Usage: Treats all clients equally, preventing resource monopolization.
  • Mitigate DoS Attacks: Defends against flooding attacks, ensuring API availability.

Imagine you're using a third-party API like Spotify, and it grants you 200 requests per day. While your site visitors may use your resource moderately, a malicious bot could exhaust your API limit within seconds.

Creating your own API allows more generous API hits, but with third-party APIs, you may need to apply a rate limit. This is crucial, especially if you're charged per API call.

For self-hosted APIs, rate limiting or throttling might be built into your framework. For example, Django Rest Framework includes a throttle class for easy implementation.

When using a third-party API, applying a rate limit at the frontend is often the best choice. It prevents unnecessary trips to the backend, improving efficiency.

What is Redis?

Redis is like a Swiss Army knife for data storage. It can do it all: caching, acting as a database, and even handling streaming tasks. With support for different data structures like strings, lists, and sets, Redis is popular in real-time applications due to its speed, flexibility, and compatibility with various data types.

When you're setting rate limits in Next.js, you can use Redis to keep track of incoming requests and their sources in real-time.

How to install Redis

If you are using debian linux, you can install Redis with:

sudo apt install redis

On other linux distros, the command might vary slighly. You can read more about how to install Redis on your linux server here.

For macOs, you can install Redis with brew:

brew install redis

Next, you need to install a Redis client in Next.js. You can install it with:

npm install ioredis

In the root of your Next.js app or utilities folder (eg ‘/utilities/rateLimit.ts’), create a file called rateLimit.ts and add the following content:

import Redis from "ioredis";

type Limit = {
maxRequests: number;
remainingRequests: number;
exceeded: boolean;
};

export const rateLimit = async (
redis: Redis,
ip: string,
maxRequests: number,
duration: number
): Promise<Limit> => {
const key = `api_throttle:${ip}`;
let requestCount = await redis.get(key);

// Parse current count, defaulting to 0
let madeRequests = parseInt(requestCount || "0", 10) || 0;

if (madeRequests >= maxRequests) {
return { maxRequests, remainingRequests: 0, exceeded: true }; // No remaining requests
}

// Increment count and set expiration time
await redis.incr(key);
await redis.expire(key, duration);

// Calculate remaining count
let remainingRequests = maxRequests - madeRequests;

return { maxRequests, remainingRequests, exceeded: false };
};

Create environment variables for Redis in your dotenv (.env) file with the following:

Redis_HOST=localhost
REDIS_PASSWORD= # provide your redis password here if you are using a password for redis otherwise leave blank
Redis_PORT=6379 # this is the default port for Redis

Next, open your Next.js API route. In the Next.js app router, this would be at, for example, '/app/api/nameofapi/route.ts/'.

Note that ‘nameofapi’ is a placeholder and should be replaced with the name of your api, eg ‘chat-api’.

Add the following to your imports at the top of the file:

import { rateLimit } from '@/utilities/rateLimit';
import Redis, { RedisOptions } from 'ioRedis';

Add this also:

const options: RedisOptions = {
host: process.env.REDIS_HOST!,
password: process.env.REDIS_PASSWORD!,
port: parseInt(process.env.REDIS_PORT!, 10),
};

In your Next.js App router API function, the part that begins with ‘export async function POST(req: NextRequest)’, add the following:


const redis = new Redis(options); 

const limit = await rateLimit(
redis,
req.ip ?? '127.0.0.1', 
maxRequests, 
60, // 1 minute
);

NextResponse.json({"X-RateLimit-Limit": limit.maxRequests, "X-RateLimit-Remaining": limit.remainingRequests})
if (!result.success) {

return NextResponse.json({ error: "Rate limit exceeded" }, { status: 429 });

That's it, access to your API should now be subject to the limit that you have applied. Happy rate-limiting!

See more posts in Websites
Author:author's avatarMichael

Recommended Posts

featured image for How to Create a Django Web App (with Custom User Model)

How to Create a Django Web App (with Custom User Model)

Learn how to create a Django web app with a custom user model, covering setup and the essential steps to tailor your application to your needs.

featured image for CSRF Attack and Implications Explained in Simple Terms With Example

CSRF Attack and Implications Explained in Simple Terms With Example

An explanation of Cross-Site Request Forgery (CSRF) attack, its implications, and effective strategies to protect web applications from unauthorized actions.

featured image for How to Trap Focus in Next.js and React

How to Trap Focus in Next.js and React

Trapping focus ensures that keyboard users can navigate your component without losing focus elsewhere on the page. Learn how to trap focus in React and Next.js.

featured image for How to Implement Debouncing in Next.js

How to Implement Debouncing in Next.js

Debouncing can be used to prevent performance issues or data inaccuracies that may arise from multiple component renderings or repetitive user actions.

featured image for Mutable vs Immutable Data in JavaScript and React.js

Mutable vs Immutable Data in JavaScript and React.js

In programming, data structures can generally be classified as either mutable or immutable. Here is a simplified explanation of both in JavaScript and React.js.