Introduction

When building modern web apps, performance, personalization, and security are no longer “nice-to-haves”—they’re expected. That’s where middleware in Next.js comes in.

Whether you need to check authentication before a page loads, redirect users based on location, or even A/B test your landing pages, middleware gives you the control you need before the request hits your actual route.

In this article, I’ll walk you through what Next.js middleware is, when to use it, and how to write your own.

What is Middleware in Next.js?

Put simply, middleware lets you run logic on the server before a request is completed—kind of like a gatekeeper for your routes.

It’s built on Edge Functions, which means it executes close to your users geographically, making it super fast and ideal for handling tasks like redirects, rewrites, and auth checks.

Unlike API route middleware (which happens inside your backend), Next.js middleware works for both pages and APIs at the routing level.

Why Should You Use Middleware?

Here are a few practical reasons I’ve found middleware useful in real-world projects:

File Structure & Setup

To get started, create a file named middleware.js (or middleware.ts) at the root of your project.

Project Structure

Next.js will automatically detect and run this middleware for every request—unless you configure it to run only on specific paths (more on that later).

Basic Example: Authentication Redirect

Let’s say you want to block unauthenticated users from accessing /dashboard. Here's a simple example,

// middleware.js
import { NextResponse } from 'next/server';

export function middleware(request) {
  const token = request.cookies.get('token')?.value;
  const url = request.nextUrl.clone();

  if (!token && url.pathname.startsWith('/dashboard')) {
    url.pathname = '/login';
    return NextResponse.redirect(url);
  }

  return NextResponse.next();
}

What’s Happening Here?

Example: Redirect Based on User Location

Let’s redirect users from outside the U.S. to a localized version of the site.

export function middleware(request) {
  const country = request.geo?.country || 'US';
  const url = request.nextUrl.clone();

  if (country !== 'US') {
    url.pathname = `/intl/${country.toLowerCase()}`;
    return NextResponse.rewrite(url);
  }

  return NextResponse.next();
}

Note: No need for external services—Next.js provides request.geo for this out of the box.

Important Limitations

There are a few gotchas to keep in mind when using middleware.

So keep your logic simple, fast, and focused.

Best Practices

Based on experience, here are a few tips that help.

When Shouldn’t You Use Middleware?

Don’t use middleware for things like,

Middleware is best for routing decisions, not rendering.

Final Thoughts

Middleware in Next.js opens up a new world of control. You can personalize experiences, secure your app, and make smarter routing decisions—all at the edge, before your app even loads.

It’s one of those features that, once you start using it, you wonder how you built without it.