R
Rishtaara
Next.js: Zero to Full-Stack
Lesson 21 of 42Article17 min

Static and Dynamic Rendering (SSG & SSR)

Static (SSG): HTML is ready at build time (or after revalidation). Fast CDN delivery. Great for docs, marketing, course lists that change slowly.

Static vs dynamic — when is HTML built?

Static (SSG): HTML is ready at build time (or after revalidation). Fast CDN delivery. Great for docs, marketing, course lists that change slowly.

Dynamic (SSR): HTML is built per request. Great for personalized dashboards, carts, anything that must be fresh or user-specific.

Real-life example: Static is a printed menu at a food stall — same for everyone, updated occasionally. Dynamic is a kitchen order ticket printed when you order — unique each time.

Next.js rendering paths

force-dynamic and revalidate

You can hint Next.js how a route should behave. Segment config and fetch options work together.

  • dynamic = 'force-static' — try to stay static
  • dynamic = 'force-dynamic' — render on every request
  • revalidate = number — time-based refresh for static pages
  • Using cookies() or headers() often forces dynamic rendering
Static with timed revalidation (ISR-style)
// app/blog/page.tsx
export const revalidate = 60; // regenerate at most every 60 seconds

export default async function BlogPage() {
  const posts = await fetch("https://api.example.com/posts", {
    next: { revalidate: 60 },
  }).then((r) => r.json());

  return (
    <ul>
      {posts.map((p: { id: string; title: string }) => (
        <li key={p.id}>{p.title}</li>
      ))}
    </ul>
  );
}
Always dynamic
// app/account/page.tsx
export const dynamic = "force-dynamic";

export default async function AccountPage() {
  // cookies(), headers(), or no-store fetch also opt into dynamic
  const res = await fetch("https://api.example.com/me", { cache: "no-store" });
  const user = await res.json();
  return <h1>Hello, {user.name}</h1>;
}

When to use each

Default to static or revalidated when content is shared. Go dynamic when correctness matters more than cache hits.

  • Static / revalidate — blog, docs, product catalog, marketing
  • Dynamic — auth dashboards, checkout, admin panels, live scores
  • Mix them — static shell + dynamic islands via Suspense (next lesson)
You do not pick SSG or SSR with a special file type anymore. App Router decides from your fetch options, segment config, and dynamic APIs.