Static vs Server Rendering in Next.js—Explained for Beginners

Posted November 17, 2025 by Karol Polakowski

Static and server rendering are two fundamental ways Next.js produces pages. Choosing between them (or using a hybrid) affects performance, SEO, developer experience, and how fresh your data can be. This article walks through the concepts, trade-offs, practical examples, and a simple decision checklist for beginner-to-intermediate developers.


Core concepts

What is Static Site Generation (SSG)?

Static Site Generation (SSG) means pages are rendered at build time into HTML files. When you deploy, users receive pre-built HTML quickly with minimal server work. Next.js exposes getStaticProps and getStaticPaths to enable SSG.

Pros:

  • Fast first load (HTML served from CDN)
  • Great SEO: fully rendered HTML available to crawlers
  • Low server cost and predictable scale

Cons:

  • Content is as fresh as your last build (unless you use ISR)
  • Not suitable for per-request personalization

What is Server-Side Rendering (SSR)?

Server-Side Rendering (SSR) generates HTML on every request. Next.js provides getServerSideProps for page-level SSR.

Pros:

  • Fresh data on each request
  • Good for pages that need request-specific data (cookies, auth headers)

Cons:

  • Higher latency because each request triggers rendering
  • More server cost under load

Incremental Static Regeneration (ISR)

ISR combines SSG performance with periodic revalidation. You build static pages, but instruct Next.js to re-generate them in the background after a configurable interval using the `revalidate` option. This is great for content that updates periodically (a blog, product pages) without rebuilding the entire site.

Practical differences and trade-offs

Performance

  • SSG: fastest for global scale—HTML can be cached at CDN edge.
  • SSR: per-request rendering adds latency; caching layers can mitigate but add complexity.
  • ISR: mostly as fast as SSG; occasional background re-generation causes a single slower request if the page is stale.

Data freshness

  • SSG: freshest on build time.
  • SSR: always fresh on each request.
  • ISR: fresh within the `revalidate` window.

SEO

Both SSG and SSR produce fully rendered HTML, which is good for SEO. Client-side rendered pages (CSR) can still be indexed, but SSG/SSR provide more predictable SEO results.

Personalization & Auth

  • SSR is straightforward for per-user content because you can read request headers, cookies, and session info during rendering.
  • SSG/ISR are less suitable for highly personalized pages unless you use client-side hydration, edge middleware, or hybrid approaches.

How to implement in Next.js (examples)

Below are small examples demonstrating SSG, ISR, and SSR pages. File names with dynamic segments must be escaped in examples.

Static generation with ISR (blog post example)

This example shows a dynamic page `pages/posts/\[slug\].js` that uses SSG plus ISR to revalidate every 60 seconds.

// pages/posts/\[slug\].js
export async function getStaticPaths() {
  // Normally fetch a list of posts from an API
  const posts = await fetch('https://api.example.com/posts').then(r => r.json())

  return {
    paths: posts.map(p => ({ params: { slug: p.slug } })),
    fallback: 'blocking' // generate pages on-demand for missing slugs
  }
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.slug}`)
  if (res.status === 404) {
    return { notFound: true }
  }
  const post = await res.json()

  return {
    props: { post },
    revalidate: 60 // ISR: revalidate at most once every 60 seconds
  }
}

export default function Post({ post }) {
  return <article>
    <h1>{post.title}</h1>
    <div>{post.content}</div>
  </article>
}

Notes:

  • fallback: ‘blocking’ lets Next.js render pages on first request and cache the result.
  • revalidate defines how often the page may be regenerated in the background.

Server-side rendering (per-request)

Use getServerSideProps for pages that must be fresh and depend on the incoming request.

// pages/dashboard.js
export async function getServerSideProps(context) {
  const { req } = context
  // Read cookie or auth token from the request
  const token = req.cookies.authToken

  // Fetch user-specific data using the token
  const res = await fetch('https://api.example.com/user/dashboard', {
    headers: { Authorization: `Bearer ${token}` }
  })
  const data = await res.json()

  return {
    props: { data }
  }
}

export default function Dashboard({ data }) {
  return <main>
    <h1>Welcome back</h1>
    <pre>{JSON.stringify(data, null, 2)}</pre>
  </main>
}

SSR is ideal when content must reflect the current user or request context.


Additional considerations

Caching and CDNs

  • For SSG/ISR, CDN caching is straightforward—serve the prebuilt HTML from edge locations.
  • For SSR, you can introduce caching headers or use internal caches (CDN with stale-while-revalidate) to reduce load, but caching increases complexity and can hurt per-user freshness.

API and Database load

  • SSR increases backend load because pages are rendered per request.
  • SSG shifts load to build time (or ISR background jobs). If your content provider rate-limits, SSG at build time can be challenging for many pages.

Build time and large sites

  • If you have thousands of pages, building them all at deploy time may be slow. Use fallback: ‘blocking’ or incremental generation (ISR) to generate pages on demand instead of pre-rendering every single page at build time.

Edge rendering and middleware

  • Next.js supports edge runtimes (Edge Functions) that can run closer to the user. Edge rendering can provide lower latency for geo-distributed users, but has limitations (smaller runtime, limited Node APIs).

Decision checklist (quick guide)

  • Use SSG when:
  • Content is mostly the same for all users
  • You want the fastest possible performance and simple caching
  • SEO matters and content updates infrequently
  • Use ISR when:
  • You want SSG performance but need periodic updates
  • Rebuilding the entire site for small content changes is impractical
  • Use SSR when:
  • Content must be fresh on every request
  • Page depends on request-specific data (auth, cookies)
  • Personalization happens at render time
  • Use client-side rendering when:
  • Content is highly interactive or personal but SEO isn’t important
  • You can defer fetching after initial load (e.g., dashboards)

Example scenarios

  • Blog or marketing site: SSG (or SSG + ISR for frequent edits)
  • Product catalog with many SKUs: ISR + fallback; stale product pages regenerate on demand
  • User dashboard: SSR (needs auth and per-request data)
  • Search or rapidly changing feeds: SSR or client-side fetching depending on SEO needs

Conclusion

Next.js gives you options—not a single solution. SSG, SSR, and ISR each have strengths. For most content-oriented public pages, prefer SSG or ISR for speed and lower cost. For per-user or highly dynamic pages, SSR (or client-rendered patterns) fits better. The right approach is often hybrid: static for general content, server-rendered for personalized paths.

Start by mapping your pages to these questions: “Does it need to be fresh on every request? Is it personalized? Will SEO be impacted?” Then pick SSG, ISR, or SSR accordingly. As you gain experience, combine patterns where they make sense and measure real-world performance under load.