React Server Components in 2026: Server by Default
React Server Components (RSC) have quietly gone from an experimental RFC to the default way modern React apps are built. The old mental model — everything is JavaScript that runs in the browser — is dead. The new one is simpler to say and harder to internalize: render on the server by default, reach for the client only where you need interactivity.
This isn't an optimization you bolt on. It changes where code runs, what data can cross the boundary, and how you reason about state.
The core idea
A Server Component runs only on the server. Its code is never shipped to the browser — it renders to a compact serialized format that the client merges into the DOM. That one property has a big consequence:
A heavy date-formatting or markdown library used inside a Server Component adds zero bytes to your client bundle.
Client Components are still here. They're just leaves of the tree now — a filter widget, a modal, an inline editor — not the trunk.
Fetch data where you render it
The biggest win is killing the request waterfall. You fetch directly in the component body: no useEffect, no loading spinner plumbing, no client fetching library.
// A Server Component — async, talks straight to the database.
export default async function PostList() {
const posts = await db.query("select id, title from posts");
return (
<ul>
{posts.map((p) => (
<li key={p.id}>{p.title}</li>
))}
</ul>
);
}
No API route, no client state, no serialization dance. The data never leaves the server except as rendered output.
Push the client boundary down
The pattern that trips teams up: treating "use client" like a page-level switch. It isn't. Mark the smallest interactive leaf, and keep everything above it on the server.
- Page and layout stay Server Components.
- Client Components are small islands at the edges.
- Server Components can render Client Components — but not the other way around.
That last asymmetry is the whole game. Internalize it and most RSC confusion disappears.
When to use which
| Need | Component type |
|---|---|
| Database / secret access | Server |
| SEO-critical content | Server |
onClick, useState, effects | Client |
| Browser APIs (localStorage) | Client |
| Heavy formatting libraries | Server |
Mutations without API routes
Server Actions let a Client Component call a server function directly — no hand-written endpoint.
"use server";
export async function publishPost(id: string) {
await db.query("update posts set status = 'published' where id = $1", [id]);
}
The takeaway
RSC isn't "React, but faster." It's the convergence of frontend and backend: the direct-database simplicity of old-school server rendering, with the interactivity of modern React layered exactly where it's needed. The teams that win treat the server/client boundary as a design decision, not an implementation detail.
Start small — one read-heavy, performance-sensitive route. Measure. Expand as the boundary behavior clicks. The architecture shift is real, but the payoff is pages that feel like static HTML with full interactivity only where it earns its place.