Next.js App Router in Production: Lessons from Real Client Projects
The mental model shift
The App Router is not the Pages Router with new folder names. It inverts the default: everything is a Server Component until you opt into the client. Teams that struggle with it are usually fighting that default — sprinkling "use client" at the top of every file and wondering why the bundle did not shrink. The win comes from pushing client boundaries to the leaves: interactive islands inside server-rendered shells.
Layouts that actually persist
Nested layouts persist across navigation — state survives, fetches do not re-run. In practice this means navbars, sidebars, and providers belong in layouts, and per-page work belongs in pages. On one client dashboard, moving a heavy user-context provider from page level into the segment layout removed a visible flash on every navigation.
Where data fetching wants to live
Fetching in Server Components with async/await removes the loading-spinner waterfall that plagued client-fetched dashboards. My rules of thumb on production projects:
- Fetch in the layout or page on the server, pass data down as props
- Use
loading.tsxand streaming for slow segments instead of blocking the whole route - Keep client-side fetching (RTK Query, SWR) for data that changes after interaction — filters, live updates, mutations
Caching is now an architectural decision
Next.js caches aggressively, and the defaults have changed across versions — which is exactly why caching needs to be explicit in code review. Tag your fetches, decide revalidation windows deliberately, and document them. The bugs that erode stakeholder trust fastest are stale-data bugs, because they look like the app is lying.
Route handlers and server actions
For form submissions and mutations, server actions remove a whole API layer for internal use cases. I still use route handlers for anything an external system calls — webhooks, integrations — because they have a stable URL contract. Mixing the two indiscriminately makes the backend surface hard to audit.
Migration advice from real projects
Migrate route by route, not big bang. The App and Pages routers coexist fine. Start with marketing or content pages where Server Components pay off immediately, leave complex authenticated dashboards for last, and budget time for the caching behavior to be re-learned by the whole team. On a recent migration, the marketing pages shipped in week one; the dashboard took a month of careful, incremental moves — and that pacing was right.
Verdict
The App Router rewards teams that embrace server-first thinking and punishes teams that fight it. The performance results are real — see the optimizations that cut our load time by 60% — but they come from using the model as designed, not from the folder rename.