React Server Components, One Month Later

First impressions after shipping a feature built on React Server Components.

We shipped our first production feature using React Server Components last month. These are my notes on what actually changed, for better and worse, once real users hit it.

The model

In RSC, components run on the server by default. Client components are the exception, marked with the "use client" directive:

async function ProductPage({ id }: { id: string }) {
 const product = await db.products.find(id);

 return (
  <>
   <h1>{product.name}</h1>
   <AddToCartButton productId={product.id} />
  </>
 );
}

The data fetching happens on the server; only the interactive island ships to the browser.

What worked

  1. No client-side waterfalls — queries start on the server.
  2. Bundle size dropped noticeably once data-fetching code stopped shipping to clients.
  3. Composing server-rendered content with small interactive pieces felt natural.

What hurt

  • Debugging serialization errors across the server/client boundary is unpleasant.
  • Every state library needed rethinking.
  • The mental model shift was bigger than the docs suggest:

It’s not “React but faster”. It’s a different split of responsibilities between server and browser.

A diagram showing server components rendering into a tree that includes client component islands

Verdict

Promising, but treat the migration as an architecture change rather than an upgrade. For this blog, incidentally, plain static HTML remains entirely sufficient — which is exactly why this site is just Markdown files.