← Volver al blog

Next.js App Router: nuestro veredicto después de 8 meses

Llevamos más de 8 meses usando App Router en producción. Esto es lo que nos gusta, lo que no nos gusta y cuándo recomendamos usarlo.

Francisco Germain

Cuando Vercel lanzó el App Router con Next.js 13, la recepción fue mixta. Los primeros meses fueron caóticos: documentación que cambiaba, bugs en el comportamiento de caché, y una curva de aprendizaje más pronunciada de lo esperado para equipos que venían del Pages Router.

Decidimos no adoptar App Router prematuramente. Lo seguimos de lejos durante los primeros meses, y empezamos a usarlo en producción hace poco más de ocho meses, cuando el ecosistema se estabilizó un poco.

Este es el resumen honesto de esa experiencia.

Lo que genuinamente nos gusta

Server Components

Esta es la feature más importante del App Router, y después de usarla en producción, entiendo por qué Vercel la presentó como un cambio de paradigma.

La idea es simple: los componentes que no necesitan interactividad corren en el servidor y envían HTML al cliente. No envían JavaScript. No necesitan hidratación. El bundle del cliente se reduce drásticamente.

// Este componente corre en el servidor. Accede a la DB directamente.
// Cero JavaScript en el cliente.
async function ProductList() {
  const products = await db.product.findMany({ where: { active: true } });
  return (
    <ul>
      {products.map(p => <li key={p.id}>{p.name}</li>)}
    </ul>
  );
}

Para aplicaciones con contenido mayormente estático o data fetching intensivo, esto es una mejora real. Los Core Web Vitals mejoran, el tiempo de interactividad baja, y el código es más simple porque no necesitás gestionar estado para datos que vienen del servidor.

Colocación del código

Con el App Router, el routing está basado en el sistema de archivos y podés colocar tus componentes, tests, y utilidades cerca del código que los usa, en lugar de tener una estructura de carpetas rígida.

app/
  dashboard/
    page.tsx
    loading.tsx
    error.tsx
    _components/
      chart.tsx
      summary-card.tsx

Esto suena menor, pero cuando el proyecto tiene decenas de rutas, tener todo lo relacionado con una ruta en el mismo lugar es una mejora real en la experiencia de desarrollo.

Layouts anidados y streaming

Los layouts anidados permiten que partes de la UI que no cambian entre navegaciones (sidebar, header de sección) no se re-rendericen. El streaming con <Suspense> permite mostrar partes de la página mientras otras todavía cargan, con loading states granulares.

export default function DashboardLayout({ children }) {
  return (
    <div className="flex">
      <Sidebar />  {/* No se re-renderiza entre rutas */}
      <main>
        <Suspense fallback={<MetricsSkeleton />}>
          {children}
        </Suspense>
      </main>
    </div>
  );
}

Para dashboards con mucha data, esto mejora la percepción de velocidad significativamente.

Lo que no nos gusta

El modelo de caché es confuso

Este fue el problema más grande que enfrentamos. El App Router tiene cuatro capas de caché diferentes: Request Memoization, Data Cache, Full Route Cache, y Router Cache. Cada una tiene comportamientos distintos, formas distintas de configurarse, y formas distintas de invalidarse.

Tuvimos bugs en producción donde datos actualizados no se mostraban porque alguna capa de caché no se estaba invalidando correctamente. Debuggear esto consume tiempo y requiere entender un modelo mental complejo.

Vercel mejoró la documentación de esto en las últimas versiones, y next@15 hizo algunos cambios que simplifican el comportamiento por defecto. Pero sigue siendo una fuente frecuente de confusión.

Mi recomendación práctica: empezá con no-store en fetch (sin caché) y añadí caché específicamente donde lo necesités, en lugar de depender del comportamiento por defecto.

La división client/server no siempre es intuitiva

Decidir qué es un Server Component y qué es un Client Component requiere pensar activamente. Usar un hook de React (useState, useEffect) en un componente lo convierte automáticamente en un Client Component. Importar un Client Component en un Server Component tiene reglas específicas.

Esto no es insuperable, pero tiene una curva de aprendizaje real. Equipos que no están acostumbrados a pensar en esta distinción cometen errores que pueden ser difíciles de detectar.

Vendor lock-in con Vercel

El App Router está diseñado por Vercel para correr en Vercel. En teoría, podés correrlo en cualquier lado. En la práctica, las features más avanzadas —caching distribuido, ISR, Edge Functions— funcionan mejor en su plataforma.

Si tu cliente tiene un requerimiento de deployment en AWS o GCP sin Vercel, o si el presupuesto de infraestructura no incluye Vercel, esto puede ser un problema.

Cuándo lo recomendamos

Sí, si:

  • Tenés una aplicación con mucho contenido que puede beneficiarse de Server Components y SSR.
  • El SEO es importante y necesitás tiempos de carga rápidos en la carga inicial.
  • Tu equipo puede dedicar tiempo a entender el modelo mental del App Router antes de usarlo en producción.
  • Estás dispuesto a deployar en Vercel o a gestionar la infraestructura adicional que implica self-hosting.

No, si:

  • Tenés un SPA puro donde casi todo es interactivo y necesita estado en el cliente. En ese caso, el App Router no te da ventajas reales y sí te da complejidad adicional. Vite + React es mejor.
  • Tu equipo viene de un proyecto grande en Pages Router y el costo de migración no tiene un beneficio claro. Pages Router sigue siendo una opción válida y mantenida.
  • Necesitás moverse muy rápido y el equipo no tiene tiempo para aprender el modelo de caché.

El veredicto

App Router es un buen producto que todavía está madurando. Las ideas core —Server Components, layouts anidados, streaming— son genuinamente buenas y representan el futuro del desarrollo web. La implementación tiene rugosidades que esperamos que se sigan puliendo.

Para proyectos nuevos donde aplica, lo recomendamos. Para proyectos existentes en Pages Router, la migración tiene un costo que hay que evaluar caso por caso.

Lo que no recomendamos es adoptarlo sin entenderlo. Las abstracciones de caché y la división client/server requieren una inversión de aprendizaje real. Si el equipo no hace esa inversión, los problemas que aparecen son difíciles de diagnosticar.


¿Estás evaluando el stack frontend de tu proyecto? Podemos ayudarte a decidir.

Francisco Germain

Founder & Arquitecto de Software, Sintaxyz

Llevo más de 6 años construyendo software para scale-ups en Latinoamérica. Escribo sobre lo que aprendo en el proceso: arquitectura, decisiones técnicas y cómo entregar proyectos que realmente funcionan en producción.

¿Tenés un proyecto donde aplica esto?

Hablemos →