React Server Components in 2025: The Honest Take
RSC is the right answer. The DX still has rough edges.
React Server Components are now the default in Next.js. The mental model is genuinely different from anything React had before. Here's what I've learned shipping them.
React Server Components shifted my mental model in a way I didn't appreciate at first.
The old model
Every component was a client component. Data fetching was hooks (useEffect, useQuery). State lived in the browser. The server's job was to ship JS that would then go fetch data and render.
The new model
Components default to server. They fetch data inline and render to HTML on the server. Client components are an opt-in for interactivity. The boundary between server and client is explicit, marked with use client.
What this changes
- Data fetching is just function calls. No hooks, no Suspense gymnastics for typical cases.
const user = await db.user.findById(id)- directly in your component. - Bundle size shrinks. Components that don't need to ship to the client don't ship to the client. My typical Next.js bundle dropped 40% on migration.
- Mental model is "two languages on one page". Server components and client components co-exist. Knowing where the boundary is becomes a skill.
What still bites
- You can't pass functions or class instances across the boundary. This is enforced by serialization. The first time you try to pass a callback to a server component you'll have a bad time.
- You can pass functions FROM server to client only via Server Actions. That works, but the model takes practice.
- Errors at the boundary are confusing. "Cannot serialize" errors are common when you import a server-only file from a client component.
My rules
- Default everything to server. Add
"use client"only when interactivity demands it. - Push client components as deep into the tree as possible. Big root client trees defeat the purpose.
- Fetch data in the server component, pass primitives down to clients.
- Use
server-onlypackage to mark code that must never ship to client. Catches mistakes at build time.
The verdict
RSC is the right model. Once you internalize it, you write less code and your apps are faster. The first month is rough; the second month is great.
If you're starting a new Next.js app today: use RSC fully. If you're migrating from Pages Router: budget the project, don't surprise yourself with effort.