DEV Community

James Perkins
James Perkins

Posted on • Originally published at jamesperkins.dev on

Rate limiting in Next.js in under 10 minutes

Rate limiting is an important feature that you need in production applications. It may sound scary, but it's actually fairly easy to implement API rate limiting in today's world. In this blog post, we'll walk through the process of implementing rate limiting using Upstash and Redis.

In this example we are using my t3-clerk-minimal app that you can find here. Make sure you have your Clerk keys in your application before starting.

What is Upstash?

upstash-home

Upstash is a serverless data stack that can be served to you on the edge using Redis or Qstash. Most people prefer Redis, and it has a really good free tier. We're going to use Upstash to implement rate limiting because they have a rate limit package that makes it dead simple to implement anywhere that you're using APIs.

First, you need to sign up for an account. Once you've done that, you'll need to click on your console and create a new database. Give it a name, and set the region to the correct region for your area (e.g. US East One or US West).

You can enable TLS if you want. Go ahead and create your Redis for Upstash.

Setting up the ENV

Now that your Redis instance has been created, you'll need to set up the ENV with your Redis REST URL and token. You can copy these information from the Upstash console.

env

From here, go to your IDE (e.g. Visual Studio Code) and add a .env file. You should already have your Upstash URLs and token in there. Close the .env file once you've pasted your Redis instance details.

Using Clerk for User Authentication

If you haven't used Clerk before, it's a user authentication and management system for the modern web, supporting frameworks like Next.js, Remix, and Gatsby. In this example, we'll be using Clerk for user authentication and protected routes.

To implement rate limiting, we need an identifier for the user (e.g. user ID, IP address) to determine if the same user is making multiple requests. We'll use the user ID from Clerk for this purpose.

Creating the Rate Limiter

First, we need to install two packages, upstash-rate-limit and upstash-redis. You can do so by running:

npm install @upstash/ratelimit @upstash/redis

Enter fullscreen mode Exit fullscreen mode

Next, import both packages in your example router and initialize the rate limiter:

import RateLimit from '@upstash/ratelimit';
import Redis from '@upstash/redis';

const rateLimiter = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(2, "3 s")
});

Enter fullscreen mode Exit fullscreen mode

This example sets a rate limit of 2 requests per 3 seconds. You can adjust the values as needed.

Implementing the Rate Limiter in a Protected Route

Now, we will implement the rate limiter in a protected route. First, create your route (in this example, we'll call it expensive). Inside the route, use the rate limiter with the user ID from Clerk:

import { TrpcError } from '@trpc/server';

// other routes
 expensive: protectedProcedure.query(async ({ ctx }) => {
    const { success } = await rateLimiter.limit(ctx.auth.userId);
    if (!success) {
      throw new TRPCError({ code: "TOO_MANY_REQUESTS" })
    }
    return "expensive"
  })

Enter fullscreen mode Exit fullscreen mode

This code checks whether the rate limit has been exceeded; if it has, a "Too Many Requests" error is thrown.

Testing the Rate Limiter

Now that the rate limiter has been implemented in your application, you can test your protected route to ensure the rate limiting is working as intended. In this example, we will test the rate limiter using a "click here to protected procedure" button on a web page.

Run your application with npm run dev, and navigate to your localhost URL. Click the button, sign in using your preferred authentication method, and you should be redirected to the protected page. Open your browser console and refresh the page - you should encounter a "Too Many Requests" error if you refresh too often.

If you wait a few seconds and refresh again, the error should be gone, indicating that the rate limiting is working as intended.

Conclusion

In this blog post, we've demonstrated how to implement rate limiting using Upstash and Redis, as well as integrating the rate limiter with Clerk for user authentication. Implementing rate limiting is an important aspect of maintaining a secure and stable production application, and this guide should help you get started in adding it to your own projects.

If you found this guide helpful, please consider subscribing to my Youtube channel or the newsletter for more tips and tutorials for web development. Happy coding!

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay