Aller au contenu principal
All notes
2026 · 04 · 8 min

The cost of an App Router migration nobody talks about

App Router migrations look like file moves. They aren't. The real work is redrawing the rendering boundary across every data fetch, every state primitive, every cache assumption.

Every team I've helped through an App Router migration starts with the same playbook: copy `pages/*` into `app/*`, swap a few imports, ship. Two weeks in, the same realization: nothing about this is mechanical.

The boundary between server and client used to be the network. Now it's a directive at the top of a file — and almost every assumption your codebase makes about state, data, and rendering crosses it. Auth providers wrapped around the tree? Client. URL state via `useSearchParams`? Different lifecycle. The Apollo cache you've been hand-feeding for three years? Gone, replaced by `fetch` and React's cache.

The migration that ships well treats the boundary as the deliverable. Map it, draw it on a whiteboard, decide where every single piece of state lives, and only then start moving files. The teams that skip this step end up with the worst of both worlds: hydration mismatches, doubled fetches, and a `'use client'` at the top of every file.

I've shipped this on M&M'S, on a couple of internal commercetools surfaces, and on a Mars corporate site. The pattern that works: pick one route, do it properly — RSC for layout and data, client islands for interactivity — measure the boundary cost, then template it across the rest.

WRITTEN BY
Ibrahim Aly
SENIOR FS ENGINEER · BERLIN ↔ CAIRO