Lesson 1 of 26
CSR, SSR and SSG: The Real Trade-offs
Client-side, server-side and static rendering compared honestly: what each actually costs in TTFB, TTI, SEO and infrastructure, and why there is no universal winner.
Every frontend system design conversation eventually asks the same question: where does the HTML the browser first sees actually come from, and when? The three foundational answers — client-side rendering, server-side rendering, and static site generation — sound like a checklist to memorize, but they are better understood as three different places to spend the same fixed amount of work: rendering the page. The question is never "which one is fastest," it's "who pays the rendering cost, and when do they pay it."
What each one actually does
Client-side rendering (CSR) ships a nearly empty HTML shell and a
JavaScript bundle. The browser downloads the bundle, executes it, and only
then builds the actual page — often after firing off its own data fetches.
React apps built with create-react-app or a plain Vite SPA are the classic
example.
Server-side rendering (SSR) runs your rendering code on a server, for every request, and sends back a complete HTML document. The browser can paint real content immediately, and JavaScript arrives afterward to make it interactive (more on why that second part is expensive in the hydration lesson).
Static site generation (SSG) does the same rendering work SSR does, but once, at build time, not per request. The output is a plain HTML file that gets deployed like an image or a stylesheet — a CDN can cache it at the edge, and no server computation happens when a real visitor shows up.
CSR — render in the browser, per visit
Fastest TTFB (the shell is nearly static), worst time-to-content, no work for crawlers to see without executing JS, cheapest server infrastructure.
SSR — render on the server, per request
Real content in the initial HTML, current data on every load, but a render cost — and a server — for every single request.
SSG — render at build time, once
Real content in the initial HTML, near-zero per-request cost, cacheable at the edge, but content is only as fresh as the last build.
The trade-offs, honestly
TTFB (time to first byte). CSR usually wins here, and it's a slightly hollow win: the server responds fast because it isn't doing any rendering work, not because the page is actually ready. SSG can match or beat it once a CDN is caching the output, because "respond" becomes "read a file already sitting at the edge." SSR sits in between — the server has to actually render before it can respond, so TTFB directly reflects render time, database latency, and whatever else that request touched.
TTI (time to interactive) and perceived load. This is where CSR's early lead evaporates. A CSR page can look blank or show a spinner for a meaningfully long time on a slow connection or an underpowered phone, because nothing meaningful exists until the JS bundle has downloaded, parsed, executed and fetched data. SSR and SSG both hand the browser real content in the first response, so there's something to paint immediately — interactivity still depends on hydration, but the user isn't staring at a blank screen while waiting for it.
SEO. Search crawlers have gotten much better at executing JavaScript, but "can eventually run your JS" and "reliably indexes exactly what a human sees, quickly, at whatever crawl budget it decided to spend on your site" are not the same guarantee. SSR and SSG both put the actual content in the first HTML response, removing that uncertainty entirely. This is precisely why marketing pages, blogs and product listings skew SSR/SSG, while an internal tool nobody needs indexed skews CSR without any real cost.
Infrastructure cost and complexity. CSR is the cheapest to run at scale — static files and a CDN, no render servers, no per-request compute. SSG is similarly cheap to serve, but the build step needs to know about every page up front, which becomes awkward once you have millions of pages or content that changes constantly (the next lesson, on ISR, exists specifically to fix this). SSR is the most expensive to operate: every request is real compute, which means real servers, real autoscaling, and a render that can fail or slow down under load in a way a static file never can.
The question that actually decides it
Not "which is best" but: how often does this content change, and does it differ per visitor? Content that's the same for everyone and changes rarely wants SSG. Content that's the same for everyone but changes constantly, or differs per request in a way you can't pre-compute, wants SSR. Content that's private, per-user, and best fetched after the shell is already up (think: a settings panel behind a login) is often perfectly happy as CSR, especially layered on top of an SSR or SSG shell for the parts that do need to be indexed or load fast.
Nearly every production app today isn't purely one of these — it's SSR for the initial shell and critical content, CSR for interactive widgets nested inside it, and SSG for anything that qualifies. Frameworks like Next.js let you make this choice per route, which is exactly why "SSR vs. SSG vs. CSR" is a question you answer per page, or even per component, not once for an entire application.
What to remember
- All three do the same rendering work — the real question is who pays for it and when: the browser per visit (CSR), the server per request (SSR), or the build once (SSG).
- TTFB and time-to-content pull in different directions for CSR: a fast empty response is not a fast usable page.
- SSR and SSG both solve SEO by putting real content in the first response; CSR relies on a crawler executing JS reliably.
- The deciding question is how often content changes and whether it differs per visitor — not which technology sounds most modern.
Check yourself
3 questions · pass 3/3 to unlock Incremental Static Regeneration
1.A marketing site with content that changes twice a month gets a surprising number of visits from search crawlers and slow mobile connections. Which rendering strategy fits best, and why?
2.Why does CSR typically have the best TTFB (time to first byte) of the three, despite often having the worst perceived load time?
3.A dashboard is only ever used by logged-in users, behind auth, and every user sees different, frequently-changing data. Which approach is the weakest fit, and why?
3 left to answer