# CSR, SSR, SSG and hydration

> Render in the browser, on each request or at build time — and the hydration cost of doing both.

Concept · Building apps · https://levelcode.org/concepts/rendering-strategies

Every page's HTML has to be produced somewhere. Where and when that happens shapes how fast the page appears, how fast it becomes usable, and what it costs to run.

| Strategy | HTML produced | First paint | Good for |
|---|---|---|---|
| **CSR** (client-side rendering) | In the browser, after JS downloads and runs | Slow: blank page or spinner until the bundle runs | Apps behind a login, dashboards |
| **SSR** (server-side rendering) | On the server, per request | Fast: real HTML arrives in the first response | Personalized or frequently changing pages that need SEO |
| **SSG** (static generation) | At build time, once | Fastest: plain files from a [CDN](https://levelcode.org/concepts/cdn) | Docs, blogs, marketing pages |
| **ISR / revalidation** | Statically, then regenerated in the background | Like SSG | Large catalogs that change occasionally |

## Hydration

SSR and SSG send HTML you can *see*, but its buttons don't work yet. **Hydration** is the browser downloading the same components' JavaScript, re-running them, and attaching event handlers to the existing HTML.

```text
SSR:  request → HTML (visible) ……… JS downloaded → hydrate → interactive
CSR:  request → empty shell → JS downloaded → render → visible + interactive
```

The costs:

- **The page looks ready before it is.** Clicks during that gap do nothing, which shows up as poor [INP](https://levelcode.org/concepts/core-web-vitals).
- **You pay to render twice,** once on the server and again in the browser.
- **Mismatches.** If the server and client render different output (dates, `Math.random()`, `window` checks during render), React warns, patches the difference, and may re-render whole subtrees.

## Reducing the hydration bill

- **Ship less JavaScript.** [Code splitting](https://levelcode.org/concepts/bundling-code-splitting) means each route hydrates only its own components.
- **Streaming SSR.** Send the shell first and stream slower sections as their data arrives, so one slow query doesn't hold up the whole page.
- **Islands and Server Components.** Render static parts on the server with **no** client JavaScript, and hydrate only the interactive pieces.

## Choosing

Start from the content. If it's the same for everyone and changes rarely, generate it statically. If it's public, personalized or fresh, and search or first paint matter, use SSR. If it sits behind a login and is highly interactive, CSR is fine; a fast spinner is acceptable there. Most frameworks let you choose **per route**, and most real sites mix all three.
