Server-Side Rendering

Render on Every Request

Server-Side Rendering

Pages that read cookies, headers, or runtime data are rendered fresh on every request — slower than static, but always up to date.

4 min read Level 2/5 #nextjs#ssr#dynamic
What you'll learn
  • Force SSR by reading `cookies()` or `headers()`
  • Use fetch with the no-store cache option to opt out of caching
  • Know the latency trade-off

SSR renders the page on every request. You give up SSG’s speed in exchange for always serving fresh, personalized data — exactly what you want for dashboards, authed pages, and anything tied to the current user.

Triggering SSR Implicitly

Any of these in a route force dynamic rendering in Next 15:

import { cookies, headers } from 'next/headers'

export default async function Page() {
  const c = await cookies()
  const token = c.get('token')?.value
  // Reading cookies() forces SSR
}

The same goes for headers() and dynamic searchParams props. Once Next sees one of these calls, it cannot prerender — the result depends on the request.

Opting a Fetch Out of the Cache

const data = await fetch('https://api.example.com/me', {
  cache: 'no-store',
}).then((r) => r.json())

no-store means “never cache this response”. The page that contains it becomes dynamic because at least one of its inputs is uncacheable.

The Trade-off

SSR pays full server cost on every request — DB queries, API calls, render time. Use it when freshness matters more than the millisecond cost. For pages that mostly stay the same, prefer SSG or ISR.

Forcing Dynamic Rendering →