Volver al blog
Desarrollo2026-05-12· 8 min

Cómo migramos una app de 8 años a Next.js sin perder un usuario.

Un caso real de migración progresiva: rutas espejo, redirecciones 301 inteligentes y por qué el SEO no solo no bajó, sino que subió un 18%.

El punto de partida era un monolito de unos 120.000 LOC: backend en PHP sobre CodeIgniter 2, una capa intermedia en Express que se añadió cuatro años después para servir endpoints JSON, y un frontend con jQuery, Handlebars y bundles que nadie se atrevía a tocar. Ocho años de parches, dos refactors abortados y una documentación que terminaba en 2019. El tráfico orgánico seguía siendo decente y eso era, paradójicamente, el mayor problema: cualquier movimiento en falso costaba sesiones reales.

Elegimos Next.js por tres razones concretas, no por moda. Primero, queríamos mantener SSR para no comernos un bajón de SEO durante la transición. Segundo, el equipo ya escribía TypeScript en otros proyectos y el ecosistema de React era el menor de los costes de aprendizaje. Tercero, el App Router nos permitía mover rutas una a una sin reescribir la app entera de golpe, que era la condición innegociable del cliente.

La estrategia se llamó internamente "rutas espejo". Levantamos la app de Next.js en el mismo dominio detrás de un reverse proxy en Nginx, con reglas que decidían ruta por ruta si la petición iba al monolito antiguo o al nuevo. Así pudimos liberar secciones pequeñas (primero el blog, luego el listado de productos, después el checkout) sin tocar el resto. Durante meses convivieron las dos aplicaciones en producción, compartiendo sesión vía cookies firmadas y un endpoint común de autenticación.

  1. Auditoría con Screaming Frog: rastreamos 47.000 URLs y las agrupamos en unos 180 clusters por URL canónica.
  2. Mapa de 301: cada cluster antiguo apuntaba a una sola URL nueva, evitando cadenas de redirecciones. Lo gestionamos en un CSV versionado y un middleware que lo cargaba al arrancar.
  3. Sitemap fusionado: generamos un sitemap.xml único que combinaba rutas viejas (las que aún no habíamos migrado) y nuevas, y lo enviamos a Search Console antes de cada release.

Las imágenes fueron un capítulo aparte. Servíamos casi 400 GB desde un bucket S3 sin CDN delante. Movimos todo a un CDN con transformaciones on-the-fly, reescribimos los <img> para usar next/image con tamaños responsive y aspect-ratio explícito, y de paso eliminamos unos 12.000 archivos huérfanos. El LCP medio bajó de 4,1 s a 1,3 s.

El SEO subió un 18% en los seis meses posteriores al corte final, y no fue magia. Fueron Core Web Vitals decentes por primera vez, datos estructurados (Article, Product, BreadcrumbList) que el monolito nunca había tenido, y URLs limpias sin parámetros heredados. Google premió lo obvio.

Fuimos tres personas durante cuatro meses: dos en frontend y migración de rutas, una en infraestructura y proxy. Lo que haríamos distinto la próxima vez: empezar por el sitemap y los 301 antes de escribir una sola línea de Next.js, y montar tests de regresión visuales desde el día uno. Nos ahorrarían dos semanas largas de retoques al final.