Devot Logo
Devot Logo
Arrow leftBack to blogs

Next.js Middleware for Beginners: How to Implement and Use It Effectively

Nikola D.5 min readMar 4, 2025Technology
Nikola D.5 min read
Contents:
What is middleware in Next.js?
Defining middleware in Next.js: structure and implementation
Use case examples of Next.js middleware
Wrapping up: the power of middleware in Next.js

Middleware is a game changer for Next.js applications. It can be a guard or a gate between incoming requests, the API or page response, allowing us to run the code before the request is completed and to modify the response accordingly. In short, it provides a way to intercept, manipulate and redirect requests on the server side ensuring flexibility and performance needed for a seamless, efficient application.

Middleware often comes to focus at the later stage of application development and when the application logic becomes a bit complex. It is not the first thing developer would think about when trying to build a web application. But if the plan is to make a secure, fast and scalable Next.js application, middleware is a tool that needs to be well understood and used.

With the latest improvements, the Next.js middleware is now more powerful and easier to deploy than ever before.

In this blog, we'll explore how to get started with Next.js middleware, configure and manage best practices, and specific use cases.

What is middleware in Next.js?

The Next.js middleware at its core is a server-side function that runs before the request completes its path to an API route or page. It acts as an intermediary between an incoming HTTP request and the final response sent to the client. Introduced with Next.js 12's revised structure, it provides a way to process and intercept request, modify or respond to the request before it reaches the actual page and intended destination. 

Functions in Next.js middleware execute during the request lifecycle which provides a centralised way to control behaviour of the application meaning tasks like authentication, redirects, or custom headers are handled in one place instead of repeating the same logic throughout the application.

How does middleware work in Next.js?

Middleware in Next.js is defined as a single function in a middleware.js (or middleware.ts) file. This file should be placed in the root of the app directory (for example, under app in the new file-based routing system).

When a request is made and the application's routing logic is about to be executed, middleware intercepts that request and, depending on the logic, modifies it, redirects it or allows it to proceed unchanged. In short words, the middleware function intercepts requests and lets you decide what happens next.

It returns a Next Response object with which we can decide how to handle the request. For example:

  • Proceed the request unchanged: using NextResponse.next() allows us to continue the request as is.

  • Redirect the user: using NextResponse.redirect() redirects the user somewhere else.

  • Rewrite the request: using NextResponse.rewrite() to change the request’s destination dynamically.

Defining middleware in Next.js: structure and implementation

Here’s a look at how middleware is defined and implemented in Next.js for handling requests efficiently.

In this example, anyone trying to access /admin without logging in will be redirected to the /login page. This ensures that only authorised users can access the admin dashboard.

The main use cases of the Next.js middleware are:

  • Centralized authentication: Use middleware to check if a user is authenticated before allowing them to access certain routes. One single check for every possible route, all in one place.

  • Logging: Middleware can be used to log requests, responses, or other information related to the application.

  • Rate limiting: Middleware can protect your server by blocking users or bots that make too many requests.

  • Error handling: Create middleware to handle errors that occur during the request processing.

  • Caching: Middleware can be used to cache responses or data to improve performance.

  • Custom redirects: Need to guide users to different pages based on their location or device? Middleware has you covered.

  • Dynamic headers and cookies: Set headers, cookies, or query parameters on the fly to personalize the user experience.

  • Bot detection: Middleware can be used to detect and block bots or malicious requests.

How to setup middleware in Next.js

To get started with Next.js middleware, create a middleware.js, or middleware.ts if you are using TypeScript, file in the root directory of the application. Here’s the most basic setup, which can be expanded due to routes customisation and request handling logic.

Configuration

Middleware will be invoked for every route in the project and with the help of config object, middleware can be limited to specific API routes or paths thus saving performance resources. Therefore, it's crucial to use matchers to precisely target or exclude specific routes.

Here’s an example of how matcher can be defined in the config object.

matcher allows multiple ways to filter Middleware, those are (as shown below): specific paths, multiple paths with an array syntax and full regex.

Use case examples of Next.js middleware

1. Redirecting users based on authentication

One of the most common uses for middleware in Next.js is to ensure that users are authenticated before accessing specific routes. This can be achieved by reading the authentication token (often stored as a cookie) and redirecting unauthorised users to a login page.

In this example, the middleware checks if an authToken cookie exists. If it doesn't, and the user tries to access the /dashboard route, they are redirected to the /login page.

2. Geo-location based routing

Next.js middleware allows access to user’s geographical location through the request.geo property, which enables location-based routing. This is ideal for localisation or delivering region-specific content.

This middleware checks the user's country and, if they are outside the US, redirects them to an international version of the page by appending /intl to the URL.

3. Rate limiting to enhance security and performance

Implementing rate limiting in middleware helps prevent abuse and protect the application from excessive requests (a common DDoS prevention tactic), from spam or malicious activity by restricting the number of requests a user can make in a given time. Here’s a simple example that limits requests based on user IP.

This rate limiter restricts users to five requests per minute, returning a 429 Too Many Requests response when the limit is exceeded.

4. Setting and modifying cookies

Next.js in middleware provides a convenient way to access and manipulate cookies through the cookies extension on NextRequest and NextResponse.

This middleware checks if a visited cookie exists; if not, it sets one. This can be useful for tracking user engagement or delivering personalised content.

5. Conditional CORS headers for API security

For API routes that handle cross-origin requests, you can set conditional CORS headers in the middleware to allow only specific origins, boosting API security.

This middleware applies CORS headers only on API routes, ensuring secure cross-origin access.

Modular middleware for complex Applications

For larger applications, breaking up middleware into modular functions can improve readability and maintainability. Instead of packing all logic into a single middleware.js file, code can be split it into smaller, reusable functions and then combined in the central middleware to perform defined tasks.

Wrapping up: the power of middleware in Next.js

Middleware might not be the flashiest part of Next.js but it is one of the most versatile and powerful tools to build smarter, faster applications with Next.js. Whether you need it for protecting the routes, personalising content or optimising performance, middleware is a way to solve the problems before they become issues.

At Devōt, we strive to enhance web development by making thoughtful technology choices. For our own digital presence, we chose Next.js to build a faster, more dynamic experience.

With this solid understanding, you can start implementing these techniques to see the difference they make in security, performance, and user experience. Dive deeper into the official Next.js middleware documentation to explore even more possibilities and start transforming your applications!

Spread the word:
Keep readingSimilar blogs for further insights
API vs UI Testing: Why a Hybrid Approach With Playwright Is the Answer
Technology
Domagoj M.6 min readJan 21, 2025
API vs UI Testing: Why a Hybrid Approach With Playwright Is the AnswerSoftware testing comes in many various types, each serving distinct purposes. Let's focus on UI and API testing and learn when to use UI testing when to rely on API testing, and how to effectively combine them with a hybrid approach.
A Developer’s Guide to Migrating Password Encryption Safely
Technology
Jerko Č.12 min readJan 7, 2025
A Developer’s Guide to Migrating Password Encryption SafelyIf you're a developer aiming to strengthen system security, this blog is for you. Learn how to update the password encryption algorithm on a live system with hundreds of thousands of active users. This guide will show you how to do it seamlessly and without disrupting your users.
Java Design Patterns: Tips, Challenges, and Best Practices
Technology
Vladimir Š.9 min readDec 20, 2024
Java Design Patterns: Tips, Challenges, and Best PracticesJava Design Patterns may seem complex at first, but once you grasp their underlying principles, they can help you organize your code for better scalability, make it easier to maintain, improve efficiency, and more.