What is Middleware(Edge runtime) in Next.js and Why You Don’t need it.

What is Middleware(Edge runtime) in Next.js and Why You Don’t need it.

Introduction

Over the last four years, I’ve worked with Next.js on numerous projects at my company — ranging from fintech to AI. However, I’ve never actually seen anyone use Next.js’s Edge functionality in a real-world scenario, and frankly, I never fully understood what it was, other than the fact that it’s another limited environment for server-side code.

Despite this, I decided to explore it in more depth to see what benefits it might offer and whether it could expand my toolkit.

What Is the “Edge”?

Vercel created Next.js to address challenges in building performant React applications. This effort led to the development of Vercel’s Edge Network, a global infrastructure designed to serve Next.js pages and static assets with minimal latency. Essentially, this network functions as Vercel’s private CDN for its clients.

Edge nodes act as intermediary servers located across the globe.

They can cache static assets like images, CSS, and pre-rendered pages and respond faster to user requests by avoiding a full round trip to the origin server. This caching mechanism significantly improves load times, but another challenge remained: database latency.

While static assets are easily cached, dynamic content often relies on database operations.

Here lies a modern problem:

— Databases can’t be distributed geographically easily due to issues like consistency, complexity, and cost.

— Long request times to distant databases continue to be a bottleneck.

Vercel couldn’t solve this entirely, but they introduced a limited workaround: Edge Functions.

In Next.js, Edge Functions — small pieces of server-side logic that execute on Edge nodes rather than centralised servers. As a result, users’ requests are handled by the nearest available server, reducing latency and potentially speeding up your application’s response times.

Yes, you read that correctly: It’s essentially like a CDN, but for executable code chunks. However, this setup currently works out of the box only when hosting on Vercel.

If you’re not a Vercel user, you can safely ignore the Edge for now without missing out on any core Next.js features.

How it works on Vercel?

In your project Next.js allows you to use Edge Functions with the Middleware.ts feature. This middleware will be executed on Edge nodes before your page is even loaded and before it reaches the server.

When you deploy your Next.js project on Vercel, the platform automatically deploys Edge code to these global Edge servers.

You don’t have to do anything extra; Vercel takes care of it for you.

This allows you to modify the request or handle logic (like redirects) without even loading your app.

Here’s the typical flow:

  1. User makes a request (e.g., /profile), this request going to Edge server.

2. Middleware at this Edge server runs and processes the request.

3. Middleware rewrites, redirects, or lets it continue to the root server.

4. The actual page is served.

If You’re Self-Hosting

If you host Next.js on your own infrastructure, Middleware still runs, but not at the Edge. This means you lose the performance benefits of geographically distributed servers. Additionally, features like request.geo won’t work since they depend on the Edge environment.

In other words, running Middleware without Edge capabilities is just like running server-side code on a central server, with no latency improvements and no built-in geo-detection.

Absolutely useless for you.

If you are Vercel User

Well, Edge Runtime is a highly constrained environment where you cannot use the Node.js standard APIs. Persistent connections, such as those required for traditional databases, are not supported, making it challenging to connect directly to relational databases in some cases. However, you can work within these limitations by leveraging serverless or connectionless databases such as Neon, PlanetScale, or FaunaDB, which are designed to function efficiently in edge and serverless architectures.

Here some use cases for this feature that I found:

Example 1: Redirecting Users

Let’s say you want to redirect users from one page to another based on a condition. I don’t know yet why redirects in next.config.js are not enough for you, but you can.

Create a middleware.js file in your project root or /pages directory:

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

export function middleware(request) {
  const url = request.nextUrl.clone();

  // Check if the user is on "/old-page" and redirect them to "/new-page"
  if (url.pathname === '/old-page') {
    url.pathname = '/new-page';
    return NextResponse.redirect(url);
  }

  return NextResponse.next(); // Continue as normal
}        

? NextResponse.redirect(): Redirects the user.

? NextResponse.next(): Allows the request to continue as usual.

Example 2: Geo-Personalization

Imagine you want to show different pages based on the user’s country.

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

export function middleware(request) {
  const country = request.geo?.country || 'Unknown'; // Geo location provided by Edge

  if (country === 'US') {
    return NextResponse.rewrite(new URL('/us-page', request.url));
  } else if (country === 'IN') {
    return NextResponse.rewrite(new URL('/india-page', request.url));
  }

  return NextResponse.rewrite(new URL('/default-page', request.url));
}        

Based on the country, you can rewrite the request to a specific page. The request.geo object is native to Edge environments like Vercel.

This approach is more practical, as you can redirect users to an entirely new data center or avoid the need to implement geo-detection logic yourself.

Example 3: A/B Testing Without Full-Page Reloads

Serve different versions of a page dynamically based on user attributes or random assignment.

Middleware can set a cookie or flag to assign users to groups.

import { NextResponse } from 'next/server';

export function middleware(request) {
  const response = NextResponse.next();
  const variant = Math.random() < 0.5 ? 'A' : 'B';

  response.headers.set('X-AB-Test', variant);
  response.cookies.set('ab-test-variant', variant);

  return response;
}        

Example 4: Enforce authentication logic globally for protected pages

Check cookies or headers for user authentication tokens in middleware.

import { NextResponse } from 'next/server';

export function middleware(request) {
  const token = request.cookies.get('auth-token');
  const url = request.nextUrl;

  if (!token && url.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  return NextResponse.next();
}        

Example 5: Custom Analytics and Logging

Middleware can send metadata about requests to a logging endpoint or analytics service.

import { NextResponse } from 'next/server';

export function middleware(request) {
  const logData = {
    url: request.nextUrl.pathname,
    timestamp: Date.now(),
    userAgent: request.headers.get('User-Agent'),
  };

  fetch('https://my-analytics-service.com/log', {
    method: 'POST',
    body: JSON.stringify(logData),
  });

  return NextResponse.next();
}        

However hard to imagine why we need it.

Combining Middleware with Static Pages

Most beneficial application of this feature on my sight is that if your Next.js app uses Static Site Generation (SSG), you can still add dynamic logic with Middleware. For example:

? Your page is statically built.

? Middleware can add dynamic behavior like personalization, geo-detection, or headers at runtime.

And depends on Edge calculation, based on geo or auth, or cookies that you can use for A/B testing, you can show one or other page.

However, keep in mind that all of these features can be implemented on a traditional server using Next.js configuration, Nginx proxies, or other techniques. The main added value of the Edge is reducing latency — somethimes by a few hundred milliseconds.

Wrap-Up

If you’re a global corporation like Google, you likely have your own robust solutions for geo-sharding.

On the other hand, if your company operates within a single country, your servers are already close to your users, making Edge solutions unlikely to be cost-effective or necessary.

To be honest, I believe practical use cases for Edge are so rare that I might never see it in action in real-world scenarios. However, if I’m mistaken and there are compelling applications for this technology, I’d love to hear about them — feel free to share your insights!

Evgenii Krilichevskii

Frontend Developer | 5years+ expert| HTML5 | CSS3 | JS | Next.js | TypeScript | Tailwind CSS | Responsive Design | Cross-Browser Compatibility

2 个月

Quite interesting info. Way to go!

Insightful dive into Edge Runtime!

??Daniil Kalugin

Senior FrontEnd Developer | 5+ years, React, TypeScript

2 个月

Interesting

Davit Gasparyan

Frontend Developer @TechWings | React, TypeScript, JavaScript | Improving UX Through Scalable Solutions

2 个月

Great breakdown of middleware and edge runtime in Next.js! Really helps clarify when and why to use these features. Insightful and well-explained! ??

要查看或添加评论,请登录

Aleksandr Ross的更多文章

  • Overengineering in React Projects

    Overengineering in React Projects

    In my 8 years as a senior frontend developer, four colleagues?—?one senior and three mid-level frontend…

  • Why I Will Not Use Index Files in?2025

    Why I Will Not Use Index Files in?2025

    Index files?—?also known as “barrel” files?—?used to seem like a neat idea. They promise a cleaner way to import…

    1 条评论

社区洞察

其他会员也浏览了