# Rendering Strategies for Modern Web Apps: CSR, SSR, SSG and Beyond

Source: https://www.egnworks.com/blog/rendering-strategies-for-modern-web-apps-csr-ssr-ssg-and-beyond  
Author: Jacob Val  
Published: 2026-05-05  
Updated: 2026-05-05  
Category: Frontend Architecture  
Tags: Rendering, JavaScript

> Learn when to use CSR, SSR, SSG, ISR, and Partial Prerendering in your web application. Includes practical decision frameworks used by senior engineers to choose the right rendering strategy per route.

---

## Introduction

Rendering strategy is one of the most consequential architectural decisions in a modern web application. The choice between server-side rendering, static generation, client-side rendering, and the newer hybrid approaches directly affects page load speed, search engine indexability, time to interactive, and infrastructure cost.

Most teams choose a rendering strategy once at the start of a project and never revisit it. This is a mistake. Different pages within a single application often have fundamentally different requirements, and a one-size-fits-all approach leaves significant performance and cost on the table.

This guide provides a clear framework for understanding the trade-offs of each rendering strategy and making the right choice for each part of your application.

## 1. Client-Side Rendering

Client-Side Rendering (CSR) delivers a minimal HTML shell to the browser and uses JavaScript to fetch data and render the UI entirely on the client. This was the dominant model for React applications from 2015 to 2020 and is still appropriate for specific use cases.

### How It Works

The server sends an HTML file with a root element and a JavaScript bundle. The browser downloads and parses the bundle, executes React, fetches data from APIs, and renders the final UI. Until this process completes, the user sees either a blank screen or a loading state.

### When to Use CSR

Authenticated dashboards and admin tools where SEO is irrelevant

Highly interactive applications where most of the user experience is driven by real-time data

Tools hosted behind authentication where initial load performance is less critical than ongoing interactivity

### When to Avoid CSR

Any page that needs to rank in search engines

Pages where Largest Contentful Paint (LCP) is a key metric

Pages served to users on slow connections or low-powered devices

```tsx
// Pure CSR with TanStack Query
"use client";

import { useQuery } from "@tanstack/react-query";

export default function DashboardPage() {
  const { data, isLoading } = useQuery({
    queryKey: ["dashboard"],
    queryFn:  fetchDashboardData,
  });

  if (isLoading) return <DashboardSkeleton />;

  return <Dashboard data={data} />;
}
```

## 2. Server-Side Rendering

Server-Side Rendering (SSR) generates the full HTML for each request on the server, sends it to the browser, and then hydrates the page with JavaScript to make it interactive. The user receives meaningful HTML immediately, before any JavaScript executes.

### How It Works

On each request, the server fetches the required data, renders the React component tree to HTML, and sends the complete document to the browser. The browser displays the HTML immediately, then downloads the JavaScript bundle and attaches event handlers through the hydration process.

### When to Use SSR

Pages with personalized content that cannot be cached, such as a user's feed or account-specific views

Pages with frequently changing data where stale content is unacceptable

Pages that need good SEO and also need to show user-specific content

```jsx
// SSR with Next.js App Router (Server Component)
import { cookies } from "next/headers";
import { getUserFeed } from "@/lib/api";

export default async function FeedPage() {
  const cookieStore = cookies();
  const userId = cookieStore.get("userId")?.value;

  // This runs on the server on every request
  const feed = await getUserFeed(userId);

  return <FeedList items={feed} />;
}
```

### The Hydration Cost

The primary drawback of SSR is hydration. After the HTML is displayed, the browser must download the full JavaScript bundle, re-render the component tree in memory, and attach event listeners. During this window, the page looks interactive but is not. On slow devices, this window can last several seconds, causing interaction failures that damage user trust and INP scores.

## 3. Static Site Generation

Static Site Generation (SSG) pre-renders pages at build time and serves the resulting HTML files from a CDN. There is no per-request server computation. The HTML is ready before the user even makes the request.

### How It Works

During the build process, the framework fetches all required data, renders every page to a static HTML file, and outputs those files to a deployment directory. A CDN serves these files globally with minimal latency.

### When to Use SSG

Marketing pages, landing pages, and documentation where content changes infrequently

Blog posts and articles where content is authored ahead of time

Product pages where inventory and pricing update on a predictable schedule

Any page where maximum performance and minimum infrastructure cost are priorities

```ts
// SSG with Next.js: generateStaticParams
export async function generateStaticParams() {
  const posts = await getAllBlogPosts();
  return posts.map((post) => ({ slug: post.slug }));
}

export default async function BlogPostPage({ params }: { params: { slug: string } }) {
  const post = await getBlogPost(params.slug);
  return <ArticleView post={post} />;
}

// Revalidate every 24 hours (ISR behavior)
export const revalidate = 86400;
```

## 4. Incremental Static Regeneration

Incremental Static Regeneration (ISR) is a hybrid strategy that combines the performance of static generation with the freshness of server-side rendering. Pages are pre-rendered at build time but can be automatically regenerated in the background when their data changes or after a specified time interval.

### Time-Based Revalidation

```jsx
// This page revalidates at most once every 60 seconds
export const revalidate = 60;

export default async function PricingPage() {
  const plans = await fetchPricingPlans();
  return <PricingTable plans={plans} />;
}
```

### On-Demand Revalidation

Rather than waiting for a time interval, on-demand revalidation triggers a page rebuild when data actually changes. A CMS webhook, an API event, or an admin action can trigger the revalidation.

```js
// app/api/revalidate/route.ts
import { revalidatePath, revalidateTag } from "next/cache";
import { NextRequest } from "next/server";

export async function POST(request: NextRequest) {
  const secret = request.headers.get("x-revalidate-secret");
  if (secret !== process.env.REVALIDATE_SECRET) {
    return Response.json({ error: "Unauthorized" }, { status: 401 });
  }

  const { path, tag } = await request.json();

  if (path) revalidatePath(path);
  if (tag)  revalidateTag(tag);

  return Response.json({ revalidated: true });
}
```

## 5. Partial Prerendering

Partial Prerendering (PPR), introduced as an experimental feature in Next.js 14 and stabilizing in 2026, is the most sophisticated rendering strategy available. It allows a single route to combine a static shell with dynamic streaming content.

### How It Works

The static parts of a page (navigation, layout, above-the-fold content) are pre-rendered at build time and served from the CDN edge instantly. Dynamic parts (personalized content, real-time data) are wrapped in Suspense boundaries and streamed from the server as they become available.

The user receives the static shell almost immediately, with dynamic content filling in progressively. This delivers the best possible LCP (from the static shell) while still supporting fully dynamic, personalized content.

```
// next.config.ts
export default {
  experimental: { ppr: true },
};
```

```tsx
// app/product/[id]/page.tsx
import { Suspense } from "react";

export default function ProductPage({ params }: { params: { id: string } }) {
  return (
    <main>
      {/* Static: pre-rendered at build time, served from CDN */}
      <ProductHero id={params.id} />
      <ProductDescription id={params.id} />

      {/* Dynamic: streamed from server per request */}
      <Suspense fallback={<PriceSkeleton />}>
        <DynamicPricing id={params.id} />
      </Suspense>

      <Suspense fallback={<InventorySkeleton />}>
        <InventoryStatus id={params.id} />
      </Suspense>
    </main>
  );
}
```

## 6. Choosing the Right Strategy Per Route

The most performant applications do not use a single rendering strategy. They use the right strategy for each route based on the data characteristics and user requirements of that route.

### Decision Framework

**Is the page publicly accessible and needs SEO?** Start with SSG or ISR.

**Does the content change frequently?** Use ISR with a short revalidation interval, or on-demand revalidation.

**Is the content personalized per user?** Use SSR or PPR with a static shell and dynamic streamed sections.

**Is the page behind authentication?** CSR is acceptable. If performance matters, use SSR or PPR.

**Does the page have both static and dynamic sections?** Use PPR.

### Practical Route Map

```
Route             Strategy    Reason
/                 SSG         Marketing, maximum performance
/blog             SSG         Static content, infrequent changes
/blog/[slug]      ISR         Per-post pages, on-demand revalidation
/products         ISR         Catalog changes, 60s revalidation
/products/[id]    PPR         Static shell, dynamic pricing/stock
/dashboard        SSR/CSR     Personalized, behind auth
/checkout         SSR         User-specific, real-time validation
/admin            CSR         Auth-gated, SEO irrelevant
```

## Conclusion

Rendering strategy is not a single choice made at project inception. It is a per-route decision that should be revisited as traffic patterns, content characteristics, and user expectations evolve.

The framework in this guide, starting from data characteristics and user requirements, then selecting the appropriate strategy, produces applications that are faster, cheaper to operate, and better positioned to scale than applications where every page uses the same approach by default.

The best rendering strategy for any given page is the one that delivers the content users need as fast as possible. Everything else is implementation detail.
