Six months with Next.js App Router: what we'd do differently

R
Rahul Patel
Head of Engineering · Mar 2025

We moved several production apps to the Next.js App Router over six months. It is a genuine step forward — and it will also happily let you build something slow and confusing if you bring your old mental model with you.

Server components change where data lives

The biggest unlearning: data fetching belongs on the server, close to the component that needs it, not hoisted into a single top-level loader. React Server Components are a React primitive rather than a Next.js one, and reading the React reference alongside the Next.js server and client components guide is what finally made the boundary make sense to us. Once that clicked, our components got smaller and our client bundles got dramatically lighter.

Caching is the footgun

The App Router caches aggressively by default across four different layers. Most of our early bugs were really caching bugs — stale data that looked like logic errors. The defaults have loosened in later releases, so check the caching model for the version you are actually on rather than trusting a blog post — including this one. Learn the cache model early and be explicit about revalidation.

Keep client components at the leaves

Interactivity should live at the edges of the tree. Pushing "use client" as far down as possible keeps the server-rendered core fast and the interactive islands small.

If your whole page is a client component, you are using a server framework to ship a single-page app.

Used with its grain, the App Router produces fast, SEO-friendly apps with very little client JavaScript. Used against it, you get the worst of both worlds.

R
Written by Rahul Patel
Head of Engineering at Satvix Tech Solutions