Next.js en el Edge: Cuando “Más rápido” se vuelve más lento (y cómo diseñarlo bien)
El renderizado en el edge puede ser un truco maestro… o un impuesto de latencia autoimpuesto. Aquí tienes cómo elegir SSR, SSG, ISR, PPR y Edge Runtime según el comportamiento real de la página, la mecánica de caché y lo que tus dashboards realmente mostrarán en producción.
El edge no es una estrategia de rendimiento. Es una ubicación de despliegue.
Suena pedante hasta que has visto una app de Next.js “movida al edge” volverse más lenta en producción: mayor TTFB, más fallos de caché, más sobrecarga de middleware, mayor gasto de cómputo, y un equipo que no puede explicar por qué porque todo era “instantáneo en local”.
El edge solo ayuda si sabes qué estás moviendo allí—y qué estás obligando a ejecutarse en cada request.
Este es un mapa pragmático de arquitecturas comunes en Next.js y los compromisos que importan: latencia, coste y complejidad. Si eres lead frontend, ingeniero full-stack o director técnico en una agencia, el objetivo es simple: elegir el modo de renderizado correcto por página, diseñar una caché que sobreviva al tráfico real e instrumentarlo todo para poder demostrarlo.
El hype del Edge vs. arquitecturas del mundo real
El discurso de marketing es limpio: ejecutar más cerca de los usuarios, reducir latencia, ofrecer experiencias más rápidas.
La realidad es más desordenada porque el rendimiento suele estar dominado por:
- Trabajo en el origen (consultas a base de datos, APIs de terceros, auth)
- Tasa de aciertos de caché (con qué frecuencia evitas trabajo en el origen)
- Cascadas (fetches en serie y consultas dependientes)
- Tamaño del payload (JS + datos)
- Middleware y personalización (forzar comportamiento dinámico)
El cómputo en el edge puede reducir la distancia de red entre usuario y servidor—pero también puede:
- Aumentar la frecuencia de cold starts (según proveedor/runtime)
- Añadir coste de cómputo por request para páginas que podrían haberse cacheado
- Fomentar la sobre-personalización que destruye la cacheabilidad
- Empujar a los equipos a una depuración distribuida sin logs adecuados
Un modelo mental útil: “¿Dónde ocurre el trabajo?”
En Next.js, cada request es alguna combinación de:
- CDN sirviendo una respuesta cacheada (lo más rápido y barato)
- Cómputo en el edge generando/transformando una respuesta
- Origen regional/serverless generando una respuesta
- Backends de datos haciendo el trabajo real (DB, búsqueda, CMS, auth)
Tu trabajo es maximizar (1), ser intencional con (2) y (3), y optimizar sin piedad (4).
Elegir modos de renderizado por tipo de página
Next.js te da múltiples estrategias de renderizado. Trátalas como una caja de herramientas, no como una religión.
SSR (Server-Side Rendering)
Mejor para: páginas muy dinámicas donde el contenido debe estar fresco en cada request.
Cuándo funciona:
- Dashboards autenticados
- Páginas sensibles a inventario/precio (a veces)
- Páginas con permisos/entitlements por request
Tradeoffs:
- Mayor variabilidad de TTFB (depende del backend)
- Más difícil de cachear globalmente a menos que segmentes respuestas
- Puede volverse caro a escala
Consejo pragmático: SSR suele ser lo correcto—pero solo si también arreglas los patrones de acceso a datos. SSR con una cascada de 3 saltos a APIs de terceros es simplemente “lento, pero más cerca”.
SSG (Static Site Generation)
Mejor para: contenido que cambia rara vez y puede precompilarse.
Cuándo funciona:
- Páginas de marketing
- Documentación
- Posts de blog
- Landing pages evergreen
Tradeoffs:
- Los tiempos de build pueden dispararse con catálogos grandes
- La frescura depende de los disparadores de rebuild
Consejo pragmático: Para agencias, SSG es la victoria por defecto. Empieza estático y añade dinamismo solo donde compense.
ISR (Incremental Static Regeneration)
Mejor para: páginas mayormente estáticas que necesitan frescura periódica sin rebuilds completos.
Cuándo funciona:
- Páginas impulsadas por CMS
- Páginas de detalle de producto con contenido no en tiempo real
- Páginas de categoría con frescura “suficientemente buena”
Tradeoffs:
- El comportamiento stale-while-revalidate puede sorprender a stakeholders
- La estrategia de revalidación se convierte en una decisión de producto
Consejo pragmático: Usa revalidación por tags (donde esté soportado) para evitar ventanas burdas basadas en tiempo.
PPR (Partial Prerendering)
Mejor para: páginas con un “shell” estable y unas pocas “islas” dinámicas.
Cuándo funciona:
- Ecommerce: info de producto estática + disponibilidad dinámica
- Páginas de contenido: artículo estático + “recomendado para ti” dinámico
- Experiencias con login: layout estático + módulo de cuenta dinámico
Tradeoffs:
- Complejidad arquitectónica: debes separar lo cacheable de lo específico por usuario
- Requiere disciplina en límites de componentes y data fetching
Consejo pragmático: PPR es donde muchos equipos creen que necesitan edge. A menudo, PPR + caché inteligente te da el 80% del beneficio con menos piezas móviles.
Edge Runtime
Mejor para: manejo de requests de baja latencia, personalización ligera, routing y comportamiento geo-aware.
Cuándo funciona:
- A/B testing en la capa de request
- Redirecciones y localización basadas en geografía
- Chequeos de token/sesión para enrutar usuarios correctamente
- Generación rápida de HTML si los datos también son rápidos y cacheables
Tradeoffs:
- Restricciones del runtime (APIs de Node no disponibles; incompatibilidades de librerías)
- Complejidad de depuración y observabilidad
- Es fácil convertir accidentalmente todo en dinámico
El edge es un multiplicador. Si tu capa de datos es lenta o no cacheable, el edge hace que el problema esté más distribuido globalmente—no resuelto.
Patrones de caché que realmente aguantan
La caché es donde las apps de Next.js ganan o pierden en producción. No necesitas “más edge”. Necesitas un plan de caché que encaje con el comportamiento de la página.
Patrón 1: Caché en CDN para tráfico público y anónimo
Si una respuesta es la misma para muchos usuarios, debería ser cacheable en la CDN.
Úsalo para:
- Páginas de marketing
- Docs públicas
- Páginas públicas de producto (en su mayoría)
Reglas generales:
- Haz que las respuestas sean cacheables por defecto y excluye solo cuando sea necesario
- Evita cookies en páginas que quieres cachear; las cookies suelen implicar personalización
Conclusión concreta: Un solo header Set-Cookie puede destruir tu tasa de aciertos de caché.
Patrón 2: Caché de fetch en Next.js para datos, no solo páginas
Next.js moderno fomenta cachear en la capa de fetch.
Úsalo para:
- Fetches de contenido de CMS
- Datos de catálogo de producto
- Llamadas a APIs no específicas por usuario
Qué vigilar:
- Cachear en exceso puede servir datos obsoletos si no tienes una historia de revalidación
- Cachear por defecto demasiado poco fuerza llamadas repetidas al backend, aumentando la latencia de cola
Conclusión concreta: Cachea las lecturas caras y compartidas (CMS, catálogo), no las lecturas personalizadas (carrito, cuenta).
Patrón 3: Revalidación por tags (el superpoder “agency-friendly”)
La revalidación basada en tiempo (revalidate: 60) es un instrumento tosco. La revalidación por tags se parece más a cómo trabajan los equipos de contenido.
Úsalo para:
- “Cuando este producto cambie, actualiza estas páginas”
- “Cuando se actualice un post, refresca su página y las páginas de listados”
Cómo aguanta en organizaciones reales:
- Funciona bien con webhooks de CMS (webhooks de Contentful, Sanity, Strapi, Shopify)
- Reduce tickets de “¿por qué el sitio sigue desactualizado?”
Si a los stakeholders les importa la frescura, dales invalidación dirigida por eventos—no un temporizador.
Patrón 4: Datos específicos por usuario: cachea alrededor de ellos, no a través de ellos
La personalización es la forma más rápida de destruir la caché.
Mejor enfoque:
- Cachea el shell de la página
- Trae datos específicos del usuario del lado del cliente o mediante un segmento dinámico pequeño
- Usa PPR/islas dinámicas para que no se fuerce toda la página a SSR
Ejemplo concreto:
- Página de producto: descripción, imágenes, especificaciones estáticas
- Dinámico: “Tu precio”, “En tu tienda local”, “Artículos en tu carrito”
Patrón 5: Evita la “explosión de claves de caché”
Incluso si cacheas, puede que estés cacheando demasiadas variantes.
Causas comunes:
- Cachear por usuario cuando solo necesitabas por país
- Incluir query strings completas en claves de caché cuando solo importa un parámetro
- A/B testing que crea demasiados buckets
Conclusión concreta: Diseña las claves de caché deliberadamente: country + language + experimentBucket suele ser suficiente. userId casi nunca lo es.
Middleware y personalización: manejar con cuidado
El middleware de Next.js es potente—y se abusa de él con frecuencia.
Trampa 1: Middleware inflado que corre en cada request
Si el middleware hace trabajo pesado (verificación de JWT, fetches remotos, routing complejo), has creado un impuesto en cada page view.
Mantén el middleware:
- Determinista
- Rápido
- Mayormente síncrono
- Sin llamadas de red siempre que sea posible
El middleware debería enrutar y anotar, no hacer fetch y computar.
Trampa 2: Sobre-personalización que fuerza renderizado dinámico
Escenario común:
- Añades una pequeña funcionalidad de personalización (p. ej., “Hola, Sam”)
- Requiere leer cookies/auth
- De repente toda la ruta se vuelve dinámica
- La caché en CDN cae casi a cero
Arreglo:
- Mueve la personalización a un componente pequeño del lado del cliente
- O aíslala detrás de un segmento dinámico (PPR/isla dinámica)
Trampa 3: Data fetching en cascada (el asesino silencioso del edge)
El SSR en el edge puede seguir siendo lento si tu servidor hace:
- Fetch de sesión
- Luego fetch de perfil de usuario
- Luego fetch de entitlements
- Luego fetch de recomendaciones
Arreglos que funcionan:
- Paraleliza requests independientes (
Promise.all) - Colapsa llamadas en un endpoint backend-for-frontend (BFF)
- Precalcula donde sea posible (p. ej., sets de recomendaciones nocturnos)
Conclusión concreta: Optimiza el grafo de dependencias antes de cambiar el runtime.
Instrumentación: demostrar rendimiento (y coste)
Si no puedes medirlo, seguirás entregando “rápido en local” y lento globalmente.
Qué medir (observabilidad mínima viable)
1) Web Vitals (real user monitoring)
Mide:
- LCP (largest contentful paint)
- INP (interaction to next paint)
- CLS (layout shift)
Usa herramientas como:
- Vercel Analytics
- Google Analytics + librería Web Vitals
- Sentry (Performance)
- Datadog RUM
2) Server timing y resultados de caché
Registra y/o emite:
- TTFB
- Estado de caché: HIT / MISS / STALE (CDN y caché de fetch)
- Duración de middleware
- Duración de render
Técnica práctica:
- Añade headers
Server-Timing(p. ej.,mw;dur=5, render;dur=40, db;dur=30) - Correlaciónalo con IDs de request
3) Tiempos de dependencias del backend
Necesitas visibilidad por dependencia:
- Tiempo de consultas a DB
- Latencia de CMS/API
- Latencia del proveedor de auth
Herramientas:
- OpenTelemetry + collector
- Spans de Sentry
- Datadog APM
Qué loguear (para poder depurar lo raro)
Loguea campos estructurados:
route,region,runtime(edge vs node)cacheKey(o un hash seguro)cacheStatususerSegment(anónimo/autenticado, no PII)experimentBucketerrorCode+ motivo del fallo upstream
Si no logueas el estado de caché, diagnosticarás mal el rendimiento durante semanas.
Observabilidad de costes (la parte que los equipos evitan)
Los costes de edge y SSR pueden sorprenderte cuando:
- Baja la tasa de aciertos de caché
- El middleware corre en cada request
- Los bots golpean rutas dinámicas
Mide:
- Requests por ruta
- Tiempo de cómputo por ruta
- Tasa de aciertos de caché por ruta
- Porcentaje de tráfico de bots (y si se salta la caché)
Acción concreta:
- Añade detección de bots y rate limiting donde corresponda
- Asegura que los bots reciban respuestas cacheadas en páginas públicas
Una matriz práctica de decisiones de arquitectura (para discovery técnico)
Úsala durante el discovery en agencia para alinear stakeholders rápidamente. Puntúa cada tipo de página y luego elige la opción más simple que cumpla los requisitos.
Paso 1: Clasifica la página por comportamiento
Para cada ruta principal, responde:
- ¿Es específica por usuario? (nada / ligera / pesada)
- ¿Qué tan fresca debe ser? (minutos / horas / días)
- ¿Qué tan caros son los datos? (baratos / moderados / caros)
- ¿Cuánto tráfico recibe? (bajo / medio / alto)
- ¿El SEO es crítico? (sí / no)
Paso 2: Elige un modo de renderizado por defecto
- SSG si: anónimo + estable + SEO importante
- ISR si: anónimo + cambia con regularidad + SEO importante
- PPR si: mayormente estático + módulos dinámicos pequeños
- SSR (Node) si: autenticado/altamente personalizado + frescura estricta
- Edge runtime si: necesitas routing/geo/experimentos en tiempo de request y puedes mantenerlo ligero
Paso 3: Aplica patrones de estrategia de caché
- Páginas públicas: caché de CDN + caché de fetch + revalidación por tags
- Páginas híbridas: shell estático + islas dinámicas para datos de usuario
- Páginas con auth: cachea fragmentos de datos (donde sea seguro), no el HTML completo
Paso 4: Valida contra modos de fallo
Checklist:
- ¿El middleware correrá en cada request? Si sí, ¿se puede simplificar?
- ¿Hay llamadas de red en middleware? Si sí, rediseña.
- ¿Hay uso de cookies en páginas pensadas para cachearse? Si sí, aísla.
- ¿Hay fetches en cascada? Si sí, paraleliza o agrega.
- ¿Tenemos visibilidad del estado de caché? Si no, añádela antes del lanzamiento.
Matriz rápida (reglas generales)
- Sitio de marketing: SSG/ISR + caché agresiva en CDN
- Hub de contenido (CMS): ISR + revalidación por tags vía webhooks
- PDP de ecommerce: PPR (producto estático + disponibilidad/carrito dinámicos)
- Búsqueda/listado: ISR o SSR según personalización; cachea resultados de query con cuidado
- Dashboard: SSR (Node) con llamadas al backend optimizadas; considera edge solo para routing/bloqueo por auth
Conclusión: diseña para cacheabilidad primero, edge después
Si quieres una arquitectura de Next.js duradera, empieza con una pregunta:
¿Qué puede ser idéntico para miles de usuarios—y por tanto cacheable?
Luego:
- Elige el modo de renderizado más simple por ruta (SSG/ISR/PPR antes que SSR)
- Diseña claves de caché y revalidación como una funcionalidad de producto (no como un añadido)
- Trata el middleware como un bisturí, no como un cajón de sastre
- Instrumenta estado de caché, timings del backend y métricas de usuario real desde el día uno
Si eres una agencia o un estudio, la victoria no es “usamos edge”. La victoria es: rendimiento predecible, tradeoffs explicables y un sistema que se mantiene rápido a medida que el sitio evoluciona.
¿Quieres una versión de esto como worksheet de discovery?
Si compartes tu lista de rutas (top 20 páginas) y fuentes de datos (CMS, DB, comercio, auth), podemos convertir la matriz de arriba en una recomendación de arquitectura de una página con modo de renderizado, plan de caché y la observabilidad mínima que necesitarás para mantenerlo honesto en producción.
