El 90% de los Desarrolladores Construye Route Handlers Sin Validación — y Les Explota en Producción
Cada vez que desplegáis un Route Handler de Next.js, TypeScript os susurra una mentira tranquilizadora: "Todo tipo correctamente."
Mentira.
TypeScript verifica tipos en compilación. Los payloads llegan en runtime. Cuando un cliente envía {"age": "treinta"} en lugar de {"age": 30}, TypeScript no puede hacer nada. Vuestro "endpoint type-safe" acaba de aceptar datos inválidos y devolver un error críptico que nadie sabe cómo parsear.
El problema real no es que falten tipos. Es que la validación de runtime es la pieza que todos omiten.
Este artículo os muestra cómo construir Route Handlers que realmente garantizan type safety: validación con Zod, envoltorios genéricos, middleware de autenticación en edge, y contratos de respuesta tipados. Todo con Next.js 16 App Router.
La Trampa del Caching en GET Route Handlers
Hay un detalle que la documentación de Next.js menciona de pasada y que destruye APIs en producción:
GET Route Handlers que retornan Response.json() se cachean por defecto en producción.
La diferencia entre Response.json() y NextResponse.json() no es obvia. Mientras Response sigue el estándar web y se cachea, NextResponse mantiene comportamiento dinámico por defecto. Pero la confusión aparece cuando accedéis a request.nextUrl.searchParams — eso también desactiva el cacheo implícitamente.
Teams descubren esto cuando sus endpoints "/api/products?filter=new" devuelven el mismo resultado durante horas. La solución trivial (export const dynamic = 'force-dynamic') requiere saber que existe el problema.
El Patrón de Validación Jerárquica en 3 Capas
La mayoría de developers añaden Zod directamente en el handler. Esto funciona, pero no escala. Cuando tienes 20 endpoints, terminas copiando código de validación en cada archivo.
El patrón que realmente escala: validación jerárquica en 3 capas.
Capa 1 — Schemas compartidos en /lib/schemas
Capa 2 — Middleware de validación en el borde
El middleware de Next.js ejecuta antes que cualquier Route Handler. Aquí es donde validáis tokens JWT, rate limiting, y headers de autenticación.
Capa 3 — Handler con validación runtime
El Envoltorio Genérico que Elimina Boilerplate
Repetir try/catch, validación, y envelopes de respuesta en cada endpoint es un desastre para mantenibilidad. Aquí entra el apiHandler.
Uso del envoltorio:
Contrato de Respuesta Tipado
El 80% de los devs devuelven { data } en éxito y { error: string } en fallo. Pero cuando un endpoint devuelve { message: 'Not found' } y otro { error: '404' }, el front-end necesita switch statements para cada caso.
El cliente consume un único contrato:
Pages Router vs App Router: La Diferencia Real
Si migráis desde Pages Router, la diferencia no es solo sintaxis. Es comportamiento.
La nueva API de streaming y Server-Sent Events (SSE) en App Router permite respuestas que fluyen gradualmente. Especialmente útil para integración con modelos de lenguaje:
Nota importante: los endpoints de streaming no pueden usar el mismo middleware pipeline que endpoints JSON tradicionales. Timeout limits también varían entre plataformas serverless — Vercel tiene límites diferentes a Railway o AWS Lambda.
Framework: El Patrón de Validación Jerárquica para Route Handlers
Aquí está el sistema completo que os recomiendo implementar:
Paso 1: Crear /lib/schemas/ con Zod
Centralizad vuestras definiciones de schema. Cada dominio (users, products, orders) tiene su archivo. Los types se inferen automáticamente con z.infer<typeof schema>.
Paso 2: Configurar middleware.ts para auth y headers
Validación de JWT, rate limiting por IP, stripping de headers inesperados. Todo antes de que el handler se ejecute. Fail fast en el edge, no en serverless.
Paso 3: Crear createApiHandler en /lib/
El envoltorio genérico que ejecuta: validación → handler → error boundary → response envelope. Cada Route Handler usa este envoltorio.
Paso 4: Exportar dynamic = 'force-dynamic' en GET
Cada GET handler que sirva datos dinámicos necesita esta línea. Olvidarla significa servir datos obsoletos en producción.
Paso 5: Compartir schemas con el front-end
Importad los mismos schemas en vuestras funciones de fetching. Si el front-end envía un campo como string cuando el backend espera number, Zod lo captura antes del viaje de red.
Objections Respondidas
"Uso tRPC — no necesito validación manual."
tRPC maneja la API principal. Pero seguís necesitando Route Handlers para webhooks de Stripe, callbacks de NextAuth, y endpoints externos. Esos paths bypassean tRPC y necesitan la misma disciplina de validación.
"Zod añade demasiado boilerplate para CRUD simple."
Un schema de 5 líneas (email, name, id) cuesta 60 segundos escribirlo. Un campo no validado causando un constraint violation en la base de datos cuesta 30 minutos de debugging. El ROI aparece en el tercer endpoint.
"Con HTTP status codes es suficiente."
Status codes categorizan errores (4xx vs 5xx). No dicen nada sobre la forma del cuerpo de error. Sin envelope consistente, cada handler de error en el front-end necesita lógica personalizada.
Resumen y Próximos Pasos
Route Handlers en Next.js App Router no son mágicamente type-safe porque TypeScript esté configurado. La seguridad real requiere validación runtime con Zod, middleware en el edge para auth, envoltorios genéricos que eliminen boilerplate, y contratos de respuesta consistentes.
El Patrón de Validación Jerárquica en 3 Capas os da la estructura para escalar de 5 a 50 endpoints sin que el código se degeneré.
Próximos pasos concretos:
- Cread
/lib/schemas/hoy — moved los primeros schemas de vuestras rutas más críticas - Implementad
createApiHandler— el boilerplate que quitáis os saveará horas - Configurad
middleware.ts— auth en el edge es más rápido y más seguro - Compartid schemas con el front-end — la misma validación funciona en ambos lados
TypeScript os da confianza. Zod os da seguridad. El patrón os da mantenibilidad.
Artículos relacionados
- Next.js en Producción: La Arquitectura que Separa los Proyectos que Escalan de los que Explotan
- Next.js 16: Las Features que el 90% de Developers Todavía No Entienden
- ISR Strategies en Next.js: La Decisión de Renderizado que Separa el Rendimiento del Caos
- Next.js 16: The 7 Features That Change How We Build Production Apps
- Vercel en Producción: La Guía Definitiva de Deployment que Nadie Escribe
---
¿Quieres recibir contenido como este cada semana? Suscríbete a mi newsletter

