Comparison Table

Rendering Method Behavior Best Use Case Next.js API
SSR Server generates a new HTML page on every request Dynamic, frequently updated data fetch(..., { cache: "no-store" })
SSG Pre-built static HTML served from cache Static content (blogs, docs) fetch(..., { cache: "force-cache" })
ISR Statically generated pages revalidated at intervals Content that updates periodically but doesn’t require real-time updates fetch(..., { next: { revalidate: X } })
CSR Browser renders content after downloading JS Highly interactive apps with minimal SEO concerns fetch() in useEffect()

Server-Side Rendering (SSR)

SSR generates a complete HTML page with dynamic data on each request, ensuring real-time updates and strong SEO. However, this increases server load and slows response times.

fetch("<https://api.example.com/data>", { cache: "no-store" });

Each time the user requests the page, the server fetches fresh data, renders the page, and sends it as fully populated HTML to the client. This ensures the most up-to-date content but can be resource-intensive, especially under heavy traffic.

Static Site Generation (SSG)

SSG pre-renders pages at build time and serves them from cache, making it fast and SEO-friendly, but static until the next build.

fetch("<https://api.example.com/data>");
// Equivalent to
fetch("<https://api.example.com/data>", { cache: "force-cache" });

Since the HTML is prebuilt, it loads almost instantly, but content won’t update until the site is rebuilt. This method is ideal for blogs, documentation sites, and marketing pages where real-time updates are not necessary.

Incremental Static Regeneration (ISR)

ISR allows static pages to be revalidated periodically, providing a balance between fast load times and fresh data.

fetch("<https://api.example.com/data>", { next: { revalidate: 60 } });

Unlike traditional SSG, ISR enables pages to automatically update at predefined intervals without requiring a full site rebuild. This is useful for news websites, product listings, and pages with semi-dynamic content.

Client-Side Rendering (CSR)

CSR loads an empty shell first, then fetches data dynamically on the client. Good for interactive apps, but less SEO-friendly.

"use client";

import { useEffect, useState } from "react";

export default function CSRPage() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch("<https://api.example.com/data>")
      .then((res) => res.json())
      .then((result) => {
        setData(result);
        setLoading(false);
      })
      .catch((err) => {
        console.error(err);
        setLoading(false);
      });
  }, []);

  if (loading) return <p>Loading...</p>;
  if (!data) return <p>No data available</p>;

  return (
    <div>
      <h1>Client-Side Rendered Data</h1>
      <p>{data.content}</p>
    </div>
  );
}

Since CSR defers fetching data until after the initial render, users might experience a delay before seeing content. This approach is best for dashboards, user-generated content, and highly interactive applications where client-side state management is essential.