Next.js 15 RSC patterns in production: 3 common mistakes
Do not mark a whole page "use client" just because one button needs state. Server Actions are not REST APIs. force-dynamic is a code smell, not a fix.
Mistake 1: "use client" on the whole page
Many devs add 'use client' to the whole page just because one component needs useState. Result: 3× JS bundle, no SSR streaming, no RSC benefits.
Correct: mark client only the components that NEED it (interaction, state, browser APIs). Server components wrap; client components nest at interactive spots.
Mistake 2: Server Actions as REST APIs
Server Actions are RPC, not REST. Do not:
- Return raw JSON for fetch
- Design URLs yourself (Next manages them)
- Use them for public APIs
Use Server Actions only for mutations triggered by form/button by a user. Public API → Route Handler.
Mistake 3: Overusing force-dynamic
Whenever a build error appears, devs slap export const dynamic = 'force-dynamic'. That is a band-aid, not a fix.
force-dynamic = every request renders from scratch. You lose all caching.
Correct: use unstable_cache + revalidateTag + time-based revalidate. Only force-dynamic when the page TRULY must re-render every request (e.g. live analytics dashboard).
Bonus: notFound() inside force-dynamic
Next 15 has a known quirk: notFound() inside a force-dynamic page returns HTTP 200 instead of 404. If you hit this, drop force-dynamic and use instead.