Skip to content
Insights
Engineering

Notes from shipping the App Router in production

What we learned moving four client codebases to React Server Components.

by Usama TariqApril 12, 20269 min

We've shipped four App Router migrations in the last year. Here's what we'd tell the next team starting.

Server Components are a layout choice, not a styling choice

The mental shift that matters: which components hold state, and which compose data. Don't try to convert page by page. Identify the data-composition boundary in your product and let that be your migration unit.

tsx
// data composition lives here
async function Dashboard() {
  const widgets = await getWidgets();
  return (
    <Shell>
      {widgets.map(w => <Widget key={w.id} data={w} />)}
      <ClientSidebar /> {/* state lives here */}
    </Shell>
  );
}

Caching is the product

Most App Router pain we've seen comes from misunderstanding the fetch cache. Read the docs once, then write a one-page cheat sheet your team agrees on. We pin ours in the repo's README.

Don't fight Suspense

If a section of your page is slow, wrap it in Suspense with a skeleton and let the rest render. This is the single biggest UX win we get from the migration.

Live · accepting briefs/lat 25.20 lon 55.27
Now booking
2 slots open
Aug '26

next kickoff · week 34

Availability · next 6 weeks
W32
W33
W34
W35
W36
W37
First reply< 24h
median · last 30d4h 12m
24hFirst reply
40+Platforms shipped
4.9★Client rating
SOC 2Ready