Next.js Middleware: Autenticação, A/B Testing e Geolocalização na Edge
O que o Middleware do Next.js resolve (e onde ele roda)
Middleware no Next.js intercepta toda requisição antes que ela chegue a uma rota, API route ou asset estático. Ele roda no Edge Runtime da Vercel (ou em qualquer runtime compatível com a Web API Request/Response), não no Node.js tradicional. Essa distinção importa: você não tem acesso a fs, child_process, nem a bibliotecas que dependem de APIs nativas do Node.js.
O ganho concreto: latência baixa para decisões que precisam acontecer antes do render. Verificar se o usuário tem token válido, decidir qual variante de A/B testing servir, redirecionar por país. Tudo isso sem tocar no SSR, sem round-trip extra ao servidor de aplicação.
O custo: o Edge Runtime tem limites reais. Sem conexão direta a banco de dados (a menos que o driver suporte HTTP, como o Neon serverless driver ou o Planetscale serverless). Sem bibliotecas pesadas. O bundle do middleware tem limite de 1 MB na Vercel. Se a lógica que você precisa executar depende de queries complexas ou processamento pesado, middleware é o lugar errado.
| Característica | Middleware (Edge Runtime) | API Route (Node.js Runtime) | Server Component |
|---|---|---|---|
| Executa antes do render | Sim | Não | Não |
Acesso a fs, APIs nativas | Não | Sim | Sim |
| Latência típica | < 5ms | 20-100ms | Depende do SSR |
| Limite de bundle | ~1 MB (Vercel) | Sem limite prático | Sem limite prático |
| Acesso a banco direto | Apenas drivers HTTP | Sim | Sim |
| Rewrite/redirect sem render | Sim | Parcial | Não |
Se você já trabalha com API Gateway patterns, o middleware do Next.js cumpre um papel similar para a camada de apresentação: interceptar, decidir e rotear.
Estrutura base do middleware
O middleware vive em middleware.ts na raiz do projeto (ou dentro de src/, se você usa essa convenção). Um único arquivo para toda a aplicação. Não existe middleware por rota como no Express. Você controla o escopo com o matcher no config.
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(request: NextRequest) {
return NextResponse.next();
}
// matcher evita que o middleware rode para assets estáticos e favicon
export const config = {
matcher: [
"/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
],
};
O matcher usa regex negativa para excluir rotas que não precisam de interceptação. Sem isso, toda requisição de imagem, CSS e JS passaria pelo middleware, adicionando latência desnecessária.
Autenticação: verificação de JWT na edge
O caso mais comum. Verificar se o usuário tem um token válido antes de servir rotas protegidas. A lógica é simples: leia o cookie ou header, valide a assinatura do JWT, redirecione se inválido.
Para validação de JWT no Edge Runtime, você não pode usar jsonwebtoken (depende de APIs do Node.js). Use jose, que é compatível com Web Crypto API.
// lib/auth-edge.ts
import { jwtVerify } from "jose";
const JWT_SECRET = new TextEncoder().encode(
process.env.JWT_SECRET!
);
export async function verifyToken(token: string) {
try {
const { payload } = await jwtVerify(token, JWT_SECRET);
return { valid: true, payload };
} catch {
// jwtVerify lança erro para tokens expirados, malformados ou com assinatura inválida
return { valid: false, payload: null };
}
}
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { verifyToken } from "./lib/auth-edge";
const PROTECTED_PATHS = ["/dashboard", "/settings", "/api/user"];
function isProtectedPath(pathname: string): boolean {
return PROTECTED_PATHS.some((path) => pathname.startsWith(path));
}
export async function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
if (!isProtectedPath(pathname)) {
return
---
Leia o artigo completo em [https://www.vivodecodigo.com.br/nextjs/nextjs-middleware-autenticacao-ab-testing-geolocalizacao](https://www.vivodecodigo.com.br/nextjs/nextjs-middleware-autenticacao-ab-testing-geolocalizacao)