LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 2716 min read

Server-Side Rendering (SSR)

Render fresh HTML on every request for pages that need up-to-the-moment or per-visitor data.

How SSR Works

With Server-Side Rendering, Next.js runs your page's Server Components fresh, on the server, for every incoming request — reading the latest data each time, then sending the resulting HTML down to that specific visitor.

Request arrives
↓
Server runs the page's Server Components right now
↓
Fresh data is fetched
↓
HTML is generated and sent back

What Makes a Route Dynamic

In the App Router, you don't flip a switch labeled "SSR" — a route becomes dynamically rendered automatically when it uses something that can only be known at request time.

Common triggers for dynamic (SSR) rendering:

  • Reading cookies() or headers().
  • Reading searchParams on a page.
  • A fetch call using { cache: "no-store" }.
  • Calling unstable_noStore() or otherwise opting a segment out of caching.

A Server-Rendered Page

// app/account/page.tsx — dynamically rendered per request
import { cookies } from 'next/headers';
export default async function AccountPage() {
const sessionId = cookies().get('session')?.value;
const account = await getAccount(sessionId); // fresh every request
return <h1>Welcome back, {account.name}</h1>;
}
Reading cookies() Opts the Whole Route In

Once any part of a page reads request-specific data like cookies(), the entire route becomes dynamically rendered — there is no partial-static exception for the rest of that page's data.

Advantages & Tradeoffs

Advantages

  • Always reflects the latest data
  • Correctly handles per-user, personalized content
  • No stale build to worry about

Tradeoffs

  • Slower than serving pre-built static HTML
  • Puts load on your server for every request
  • Can't be fully cached at the CDN edge

FAQs

Conceptually yes — both render fresh HTML per request — but in the App Router it happens implicitly, based on what data APIs a Server Component uses, rather than a named exported function.

Yes — you can wrap slower, cacheable pieces in their own fetch with caching enabled, or use React's cache() function, even while the outer route is dynamic.

Summary

SSR trades some speed for guaranteed freshness and per-request personalization. Next, you'll see Incremental Static Regeneration, which aims to get most of the speed of SSG with much of the freshness of SSR.

Next Lesson →

Incremental Static Regeneration