Middleware en Next.js 16 en 2026: Edge Runtime, Autenticación y Preguntas de Entrevista
Domina el middleware de Next.js 16 con Edge Runtime, patrones de autenticación y preguntas técnicas de entrevista para desarrolladores frontend.

El middleware de Next.js 16 se ejecuta antes de cada solicitud, convirtiéndolo en la primera línea de defensa para autenticación, localización y manipulación de solicitudes. Comprender el funcionamiento del middleware es esencial para construir aplicaciones de producción y constituye un tema frecuente en entrevistas técnicas de frontend.
El middleware de Next.js 16 se ejecuta en el Edge Runtime por defecto, lo que significa que funciona en centros de datos cercanos a los usuarios con tiempos de arranque en frío inferiores al milisegundo. Esto lo hace ideal para verificaciones de autenticación y redirecciones que deben ocurrir antes de que la página se renderice.
Cómo Funciona el Middleware de Next.js 16 Internamente
El middleware en Next.js 16 intercepta las solicitudes antes de que lleguen al manejador de ruta o al componente de página. El archivo de middleware debe colocarse en la raíz del proyecto (junto a app/ o pages/) y exporta una función por defecto que recibe un objeto NextRequest.
La restricción del Edge Runtime significa que el middleware no puede utilizar APIs de Node.js como fs o Buffer. Se ejecuta en aislados V8, similar a Cloudflare Workers, lo que permite distribución global pero limita las APIs disponibles a los estándares Web.
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Acceso a headers, cookies y URL de la solicitud
const token = request.cookies.get('session')?.value
const pathname = request.nextUrl.pathname
// Log para depuración (visible en logs de Vercel)
console.log(`Middleware: ${request.method} ${pathname}`)
// Continúa hacia el manejador de ruta
return NextResponse.next()
}
// Configura qué rutas activan el middleware
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}La configuración matcher utiliza una sintaxis similar a regex para definir qué rutas activan el middleware. Sin esta configuración, el middleware se ejecuta en cada solicitud, incluyendo los assets estáticos.
Patrones de Autenticación con Middleware de Next.js
El middleware sobresale en la protección de rutas que requieren autenticación. En lugar de verificar la autenticación en cada componente de página, una verificación centralizada en el middleware garantiza que ninguna ruta protegida pueda ser accedida sin una sesión válida.
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
const protectedRoutes = ['/dashboard', '/settings', '/profile']
const authRoutes = ['/login', '/register']
export function middleware(request: NextRequest) {
const token = request.cookies.get('session')?.value
const pathname = request.nextUrl.pathname
// Verifica si la ruta requiere autenticación
const isProtectedRoute = protectedRoutes.some(route =>
pathname.startsWith(route)
)
const isAuthRoute = authRoutes.some(route =>
pathname.startsWith(route)
)
// Redirige usuarios no autenticados a la página de login
if (isProtectedRoute && !token) {
const loginUrl = new URL('/login', request.url)
loginUrl.searchParams.set('callbackUrl', pathname)
return NextResponse.redirect(loginUrl)
}
// Redirige usuarios autenticados fuera de páginas de auth
if (isAuthRoute && token) {
return NextResponse.redirect(new URL('/dashboard', request.url))
}
return NextResponse.next()
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}Este patrón maneja tanto la protección de rutas como la prevención de acceso a páginas de login para usuarios ya autenticados.
Validación JWT en el Middleware Edge
Validar tokens JWT en el edge requiere bibliotecas compatibles con Edge Runtime. El paquete jose es la elección estándar porque utiliza las APIs Web Crypto disponibles en el entorno Edge.
import { jwtVerify } from 'jose'
const JWT_SECRET = new TextEncoder().encode(
process.env.JWT_SECRET || 'your-secret-key'
)
export async function verifyToken(token: string) {
try {
const { payload } = await jwtVerify(token, JWT_SECRET)
return { valid: true, payload }
} catch (error) {
return { valid: false, payload: null }
}
}import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { verifyToken } from './lib/auth-edge'
export async function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token')?.value
if (!token) {
return NextResponse.redirect(new URL('/login', request.url))
}
const { valid, payload } = await verifyToken(token)
if (!valid) {
// Elimina la cookie inválida y redirige
const response = NextResponse.redirect(new URL('/login', request.url))
response.cookies.delete('auth-token')
return response
}
// Agrega información del usuario a los headers para Server Components
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-user-id', payload?.sub as string)
requestHeaders.set('x-user-role', payload?.role as string)
return NextResponse.next({
request: { headers: requestHeaders },
})
}Pasar información del usuario a través de headers permite que los Server Components accedan a datos de autenticación sin consultas adicionales a la base de datos.
Manejo de Internacionalización en el Middleware
El middleware es el lugar ideal para manejar la detección de idioma y las redirecciones. Next.js 16 proporciona helpers integrados para internacionalización que funcionan en el Edge Runtime.
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
const locales = ['en', 'fr', 'de', 'es', 'ja']
const defaultLocale = 'en'
function getLocale(request: NextRequest): string {
const negotiatorHeaders: Record<string, string> = {}
request.headers.forEach((value, key) => {
negotiatorHeaders[key] = value
})
const languages = new Negotiator({ headers: negotiatorHeaders }).languages()
return match(languages, locales, defaultLocale)
}
export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname
// Verifica si el pathname ya tiene un locale
const pathnameHasLocale = locales.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
)
if (pathnameHasLocale) return NextResponse.next()
// Redirige al pathname con locale
const locale = getLocale(request)
const newUrl = new URL(`/${locale}${pathname}`, request.url)
return NextResponse.redirect(newUrl)
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}Rate Limiting en el Edge
Implementar rate limiting en el middleware protege las APIs contra abusos. Los contadores en memoria no funcionan de manera confiable en el edge debido a su naturaleza distribuida, pero soluciones externas como Upstash Redis proporcionan almacenamiento compatible con Edge.
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { Ratelimit } from '@upstash/ratelimit'
import { Redis } from '@upstash/redis'
const redis = new Redis({
url: process.env.UPSTASH_REDIS_URL!,
token: process.env.UPSTASH_REDIS_TOKEN!,
})
const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(10, '10 s'),
analytics: true,
})
export async function middleware(request: NextRequest) {
// Solo limita rutas API
if (!request.nextUrl.pathname.startsWith('/api')) {
return NextResponse.next()
}
const ip = request.ip ?? '127.0.0.1'
const { success, limit, reset, remaining } = await ratelimit.limit(ip)
if (!success) {
return NextResponse.json(
{ error: 'Too many requests' },
{
status: 429,
headers: {
'X-RateLimit-Limit': limit.toString(),
'X-RateLimit-Remaining': remaining.toString(),
'X-RateLimit-Reset': reset.toString(),
},
}
)
}
return NextResponse.next()
}Modificación de Headers de Respuesta
El middleware puede modificar headers de respuesta para políticas de seguridad, caché y headers personalizados. Esto ocurre después del procesamiento de la ruta pero antes de enviar la respuesta al cliente.
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const response = NextResponse.next()
// Headers de seguridad
response.headers.set('X-Frame-Options', 'DENY')
response.headers.set('X-Content-Type-Options', 'nosniff')
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
response.headers.set(
'Content-Security-Policy',
"default-src 'self'; script-src 'self' 'unsafe-inline'"
)
// Headers personalizados para depuración
response.headers.set('X-Middleware-Timestamp', Date.now().toString())
return response
}Manejo de Errores en el Middleware
El middleware debe manejar errores de manera elegante para evitar bloquear solicitudes. Los errores no capturados en el middleware resultan en una respuesta 500, lo que puede bloquear el acceso a toda la aplicación.
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export async function middleware(request: NextRequest) {
try {
// Operaciones del middleware que pueden fallar
const token = request.cookies.get('session')?.value
if (token) {
const isValid = await validateSession(token)
if (!isValid) {
return NextResponse.redirect(new URL('/login', request.url))
}
}
return NextResponse.next()
} catch (error) {
// Registra el error pero no bloquea la solicitud
console.error('Middleware error:', error)
// Opciones: continuar, redirigir a error, o retornar respuesta de error
return NextResponse.next()
}
}
async function validateSession(token: string): Promise<boolean> {
// Lógica de validación
return true
}¿Listo para aprobar tus entrevistas de React / Next.js?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Preguntas de Entrevista: Middleware de Next.js
Las preguntas de entrevista sobre middleware evalúan la comprensión de su modelo de ejecución, limitaciones y casos de uso apropiados.
Pregunta: ¿Cuál es la diferencia entre middleware y API Routes para autenticación?
El middleware se ejecuta antes de los manejadores de ruta y puede interceptar solicitudes a cualquier ruta, incluyendo páginas estáticas y assets. Las API Routes solo se ejecutan para solicitudes a /api/*. El middleware es ideal para verificaciones de autenticación a nivel de toda la aplicación, mientras que las API Routes manejan lógica de negocio específica.
Pregunta: ¿Por qué no se pueden usar APIs de Node.js en el middleware?
El middleware se ejecuta en el Edge Runtime, que utiliza aislados V8 en lugar de un entorno Node.js completo. Esto permite arranques en frío inferiores al milisegundo y distribución global, pero limita las APIs disponibles a los estándares Web (fetch, crypto, etc.).
Pregunta: ¿Cómo se pasan datos del middleware a los Server Components?
Estableciendo headers personalizados en la solicitud usando NextResponse.next({ request: { headers: modifiedHeaders } }). Los Server Components pueden entonces leer estos headers usando la función headers() de next/headers.
Pregunta: ¿Cuál es el enfoque correcto para el manejo de sesiones en el middleware?
Leer cookies de sesión y validar tokens usando bibliotecas compatibles con Edge como jose para JWT. No realizar consultas de base de datos directamente en el middleware; en su lugar, usar validación de tokens o APIs de sesión externas.
Pregunta: ¿Cómo se implementa una cadena de middlewares en Next.js?
Next.js solo soporta un único archivo de middleware, pero se pueden encadenar múltiples funciones componiéndolas:
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
type MiddlewareFunction = (
request: NextRequest
) => Promise<NextResponse | null>
const withAuth: MiddlewareFunction = async (request) => {
const token = request.cookies.get('session')?.value
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url))
}
return null
}
const withLogging: MiddlewareFunction = async (request) => {
console.log(`${request.method} ${request.nextUrl.pathname}`)
return null
}
const middlewares = [withLogging, withAuth]
export async function middleware(request: NextRequest) {
for (const mw of middlewares) {
const result = await mw(request)
if (result) return result
}
return NextResponse.next()
}Mejores Prácticas para Middleware en Producción
Minimizar el trabajo realizado en el middleware mejora los tiempos de respuesta. Cada milisegundo en el middleware retrasa el renderizado de la página. Evitar llamadas a APIs externas a menos que sea absolutamente necesario.
Usar el matcher apropiadamente reduce las ejecuciones innecesarias del middleware. Excluir archivos estáticos, imágenes y rutas API que no requieren procesamiento de middleware.
export const config = {
matcher: [
// Coincide con todos los paths excepto archivos estáticos
'/((?!_next/static|_next/image|favicon.ico|public/).*)',
// O lista explícita de rutas
'/dashboard/:path*',
'/api/protected/:path*',
],
}Los logs en el middleware deben ser mínimos en producción. Cada console.log agrega latencia y consume recursos.
Conclusión
El middleware de Next.js 16 proporciona una poderosa capacidad de intercepción de solicitudes que se ejecuta en el edge con latencia mínima. Comprender sus restricciones (Edge Runtime, sin APIs de Node.js) y sus casos de uso apropiados (autenticación, i18n, rate limiting) es esencial para construir aplicaciones de alto rendimiento. Los candidatos deben poder explicar la diferencia entre middleware y API Routes, demostrar manejo de errores apropiado y comprender cómo pasar datos a los Server Components.
¿Sabrías detectar el bug en React / Next.js?
Un fragmento real, un bug oculto, un intento al día. Sin cuenta para probar.

Escrito por
Anthony Fillion-MailletFundador de SharpSkill
Desarrollador fullstack desde hace más de 10 años. Dirige SharpSkill y responde por todo lo que se publica aquí.
Actualizado el 20 de septiembre de 2026
Etiquetas
Compartir
Artículos relacionados

Preguntas de entrevista sobre Zustand 2026: Gestión de estado en React y mejores prácticas
Prepara tus entrevistas técnicas con esta guía completa sobre Zustand. Descubre las preguntas frecuentes, patrones de middleware, comparación con Context API y mejores prácticas de TypeScript.

React 19 Suspense y Renderizado Concurrente: Streaming SSR y Preguntas de Entrevista 2026
Guía completa sobre React 19 Suspense, renderizado concurrente y Streaming SSR. Patrones avanzados y preparación para entrevistas técnicas en 2026.

Testing en React 2026: Vitest, React Testing Library y Mejores Prácticas
Dominar el testing en React con Vitest y React Testing Library. Aprender patrones de testing de componentes, manejo asíncrono, estrategias de mocking y mejores prácticas para entrevistas técnicas en 2026.