What Server Side Rendering Solves

Photo: Lukas Blazek / Pexels
A page built entirely with client-side JavaScript sends the browser an almost empty HTML file, a single <div id="root"></div> and a script tag, and asks the browser to construct the entire visible page after that script downloads, parses, and executes. Server-side rendering (SSR) — running the page-building code on the server instead of the browser, so the response already contains finished HTML — flips that order. The browser receives complete, visible markup immediately, before a single line of JavaScript has run. This article explains exactly what problem that solves, what it doesn't, and how it compares to the other rendering strategies developers reach for instead.
The problem SSR was built to fix
Client-side rendered single-page applications, popularized by frameworks like early React and Angular in the mid-2010s, moved essentially all rendering logic into the browser. The server's only job became handing over a nearly blank HTML shell and a JavaScript bundle; everything the user actually sees gets assembled client-side, in the browser's own JavaScript engine, after that bundle finishes loading.
That architecture works fine once the JavaScript has downloaded, parsed, and executed. The trouble is the gap before that point. Between the moment the initial HTML arrives and the moment the JavaScript finishes building the DOM, the user is staring at a blank page or a loading spinner. On a fast laptop with a strong Wi-Fi connection, that gap might last a few hundred milliseconds and go unnoticed. On a mid-range Android phone over a throttled 4G connection, that same gap can stretch past several seconds, long enough that a meaningful share of visitors simply leave.
Search crawlers compounded the problem in a way that's easy to underestimate. Google's crawler, Googlebot, can execute JavaScript, but it does so in a deliberately separated step. Google's own developer documentation describes a two-phase process: Googlebot first crawls and indexes the raw HTML it receives, then queues the page for a second rendering pass where a headless version of Chrome actually executes the JavaScript and re-crawls the resulting DOM. That second pass does not happen instantly — it lands in a rendering queue, and the wait between the first crawl and the JavaScript-rendered crawl is variable, sometimes minutes, sometimes considerably longer during periods of high queue load. A purely client-rendered page is, for that entire window, indexed based on an HTML document that might contain almost nothing.
Other automated visitors are less forgiving still. Many social media link-preview bots — the systems that generate the title, description, and thumbnail card when a link gets shared — don't execute JavaScript at all. They read whatever is in the initial HTML response and stop there. A client-only rendered page can hand these bots an empty shell with no title, no description, and no image, which is why link previews for JavaScript-heavy sites sometimes show up blank or generic on platforms like X or Facebook.
How SSR actually works
With SSR, the exact same component code that would otherwise run in the browser runs on the server instead, once per incoming request. That server process produces a complete HTML document, with the real content — the text, the layout, the data already fetched and inserted — filled in before the response ever leaves the server. The browser receives that finished document and can paint it to the screen immediately, without waiting on any script to execute first.
Frameworks automate the mechanics of this. Next.js, built by Vercel, and Nuxt, built for the Vue ecosystem, both run a page's rendering logic on the server for each request, serialize the output into an HTML string, and send it down the wire. What comes after is a process called hydration — the step where the client-side JavaScript bundle, once it does load, attaches event listeners and interactive behavior to the HTML that's already sitting on the page, rather than rebuilding the entire DOM from scratch. Instead of "build everything," the browser's job during hydration is closer to "recognize what's already there and wire it up."
This distinction matters because it explains why SSR feels different from simply pre-rendering a static file. A static HTML file, generated once at build time, is the same for every visitor. SSR generates HTML on the fly per request, which means it can safely include data that changes — a logged-in user's name, a live inventory count, a personalized recommendation — because the render happens at the moment of the request, not weeks earlier at build time.
Why hydration exists at all
Hydration — the process of attaching interactivity to already-rendered HTML rather than generating that HTML in the browser — exists because SSR only solves the display half of the problem. A server-rendered button looks like a button the instant the page loads, but it does nothing until JavaScript runs and attaches a click handler to it. Hydration is that attachment step, and it still requires downloading and executing a JavaScript bundle roughly comparable in size to what a purely client-rendered app would need.
Where SSR provides a measurable benefit
The specific, documentable gains from SSR cluster around a handful of areas, and understanding which ones apply to a given project is more useful than treating SSR as a blanket performance upgrade.
Search engine visibility. Search engines receive fully formed HTML on the very first crawl, removing any dependency on the JavaScript-rendering pass succeeding, completing quickly, or completing at all. This is the single most commonly cited reason development teams choose SSR or static generation over pure client-side rendering for anything that needs to rank in search.
Largest Contentful Paint (LCP). LCP is one of Google's three Core Web Vitals — the metric measuring how long it takes for the largest visible element (usually a hero image or a block of text) to render on screen, with Google's guidance treating 2.5 seconds or less as "good." Because SSR delivers already-built HTML, the browser doesn't have to wait for a JavaScript bundle to download and execute before it can paint the page's main content, which tends to pull LCP times down, especially on slower networks or lower-powered devices where JavaScript execution itself is the bottleneck.
Social media link previews. Services that scrape a page's meta tags to build a preview card when a link is shared often skip JavaScript execution entirely. SSR guarantees they receive the correct title, description, and image tags on the first request, rather than an empty shell.
Accessibility for constrained clients. Any browser, bot, or assistive technology that can't or won't run JavaScript still receives usable, readable content, rather than a blank page it has no way to fill in.
| Strategy | Where HTML is built | Typical TTFB | SEO friendliness | Best use case |
|---|---|---|---|---|
| Client-side rendering (CSR) | Browser, after JS executes | Fast (near-empty response) | Weak — depends on delayed JS crawl | Authenticated dashboards, internal tools |
| Server-side rendering (SSR) | Server, per request | Slower than static (server does work per request) | Strong — full HTML on first crawl | Pages with per-request or personalized data |
| Static site generation (SSG) | Server, at build time | Fastest (pre-built file served from CDN) | Strongest — identical HTML every time | Marketing pages, blogs, docs |
| Incremental static regeneration (ISR) | Server, at build time + on a schedule | Fast (served like static, refreshed periodically) | Strong — mostly static with periodic updates | Product catalogs, news pages that update but not per-request |
Static generation wins on raw speed because the work happens once at build time; SSR trades some of that speed for the ability to include fresh, per-request data; ISR tries to split the difference by rebuilding static pages on a timer instead of on every request.
What SSR does not solve
SSR relocates where rendering computation happens. It does not remove JavaScript from the page, and it does not make the page interactive any faster than the JavaScript bundle allows. The browser still has to download, parse, and execute essentially the same JavaScript it would have needed for hydration to work, meaning a page can display fully readable content while remaining completely unresponsive to clicks or taps until that hydration step finishes.
This distinction shows up directly in Google's Core Web Vitals. Interaction to Next Paint (INP) — the metric that replaced First Input Delay (FID) as a Core Web Vital in March 2024, measuring how quickly a page responds to a user's interaction — is governed by how much JavaScript has to run on the main thread, not by how the initial HTML got there. A page with excellent LCP thanks to SSR can still post a poor INP score if its JavaScript bundle is large, poorly split, or blocking the main thread during hydration.
SSR also adds real computational cost on the server side. Every incoming request now triggers a fresh render, work that a purely static file wouldn't require at all. That per-request cost is why high-traffic sites frequently layer caching in front of their SSR responses, or shift pages that don't need fresh data on every load over to static generation or incremental static regeneration instead. Next.js explicitly supports mixing these strategies page by page within a single application, letting a team use SSR only where per-request freshness actually matters.
How ISR tries to split the difference
Incremental Static Regeneration (ISR) — a Next.js rendering strategy that serves pre-built static HTML but regenerates it in the background on a set schedule or trigger — exists specifically to capture SSR's freshness without paying its per-request server cost. A product page can be statically generated, served instantly from a CDN edge node, and quietly rebuilt every few minutes so the price and stock count stay reasonably current, without every single visitor forcing a fresh server render.
How streaming and React Server Components extend SSR
Classic SSR has one structural limitation baked into how it works: the server has to finish rendering the entire page, every component and every data fetch, before it can send back a single byte. If one section of a page depends on a slow database query or a third-party API call, the whole response waits on that slowest piece, even if every other part of the page was ready to send instantly.
Streaming SSR, built on React 18's streaming renderer, changes that by sending HTML in chunks as each piece finishes rendering, instead of holding the entire response until everything is done (React documentation on Suspense and streaming, referenced in Next.js's own streaming guide, nextjs.org). A page's static shell, its layout, navigation, and any content that doesn't depend on a slow data source, gets sent to the browser immediately. Sections that do depend on a slower fetch are wrapped in a <Suspense> boundary, which shows a fallback (a loading skeleton, for instance) in that spot until the real content is ready, at which point the server streams in the finished HTML and a small inline script swaps it into place, without requiring the whole page's JavaScript bundle to load first.
React Server Components (RSC), the architecture Next.js's App Router is built around, push this further by letting individual components run exclusively on the server and never ship their component code to the browser at all. A server component that fetches and formats data sends only the resulting HTML to the client, with none of the JavaScript needed to run that component included in the bundle, which means it needs no hydration step for that piece of the page. Client components, marked explicitly with a "use client" directive, still hydrate as before for anything genuinely interactive, like a button or a form. The practical effect is a smaller JavaScript bundle overall, because logic that only ever needs to run once, on the server, to produce HTML never has to be shipped to and re-executed inside the browser.
How is streaming SSR different from just adding a loading spinner?
A loading spinner shown by client-side JavaScript still requires the browser to first receive and parse a mostly empty page before it can even render that spinner. Streaming SSR sends real, styled HTML for the page's fallback state directly from the server on the very first response, then progressively replaces specific sections in place as their data resolves, without a client-side round trip to fetch that structure.
This distinction matters most for pages built around a genuinely slow dependency, a third-party API, a large aggregation query, a report that takes real time to assemble, where waiting for the single slowest piece under classic SSR could otherwise delay every other part of an already-ready page.
What people get wrong about SSR
A common misconception is that SSR makes a site faster in every measurable sense, full stop. In practice, SSR primarily improves the time until visible content appears on screen. A poorly optimized SSR setup can still post a slow Time to Interactive if the JavaScript bundle needed for hydration is large or loaded inefficiently — the page looks done well before it actually is.
A second mistake is assuming SSR is no longer necessary because modern search crawlers can execute JavaScript anyway. Google's own JavaScript SEO documentation is explicit that rendering happens in a separate, queued pass that can be delayed, which means pages depending entirely on client-side rendering can be indexed more slowly, or less completely, than equivalent pages using SSR or static generation. "Google can technically do it" and "Google does it immediately and reliably at scale" are different claims, and the gap between them is exactly the gap SSR closes.
A third, subtler mistake is treating SSR and static generation as interchangeable. They solve overlapping problems but at different costs: SSR is the right tool when a page genuinely needs per-request data — a logged-in user's account balance, a search results page, live pricing — while static generation or ISR is the better fit when the content is effectively the same for every visitor and doesn't need to be rebuilt on every single request. Reaching for SSR on a page that could be static adds server load and latency with no corresponding benefit.
When SSR is the right call
The decision usually comes down to one question: does this specific page's content depend on data that's different for every request, or on data known well in advance? A marketing homepage, a blog post, or a documentation page rarely changes between one visitor and the next, which makes it a strong candidate for static generation. A personalized dashboard, a live search results page, or a checkout flow with real-time inventory checks genuinely needs to render fresh, per-request, which is exactly the case SSR is built for.
Teams building with a framework like Next.js or Nuxt don't have to pick one strategy for an entire application. Both frameworks support choosing a rendering strategy on a route-by-route basis, so a single site might statically generate its marketing pages, server-render its account dashboard, and use ISR for a product catalog that updates every few minutes rather than every millisecond. Understanding which category a given page falls into, before defaulting to whichever strategy the team used last time, is what keeps a site fast without adding unnecessary server load. This kind of strategy-per-route thinking connects directly to broader questions about how browsers render web pages in the first place, since SSR's entire value proposition rests on shortening the gap between an HTTP response landing and the browser having something to paint.
The takeaway
Server-side rendering solves a specific, well-defined problem: the gap between a browser receiving a response and that response actually containing meaningful, visible content. By running rendering logic on the server and sending complete HTML immediately, SSR gets content in front of both users and search crawlers faster and more reliably than an empty shell waiting on client-side JavaScript ever could. It does not, on its own, make a page's JavaScript smaller, its hydration faster, or its Interaction to Next Paint better — those depend on how much script the page ships and how efficiently that script runs once it arrives, a distinction that matters as much for why web performance affects SEO broadly as it does for SSR specifically. Choosing SSR, static generation, or ISR is less about picking a universally "faster" option and more about matching the rendering strategy to whether a given page's content is the same for everyone or genuinely needs to be built fresh for each request.
Read next:
- How Browsers Render Web Pages
- Why Web Performance Affects SEO
- Why Structured Data Helps Search Engines
FAQ
Q: What is the main difference between SSR and client-side rendering?
With client-side rendering, the browser receives minimal HTML and builds the entire page in the browser after JavaScript downloads and executes. With SSR, the server runs that same rendering logic ahead of time, for each request, and sends complete, visible HTML immediately, before any JavaScript has run.
Q: Does SSR make a page fully interactive faster?
Not necessarily. SSR speeds up when content becomes visible on screen, but the browser still needs to download and execute JavaScript to attach interactivity through hydration. Time to Interactive and Interaction to Next Paint depend mainly on JavaScript bundle size and execution cost, regardless of whether the page used SSR.
Q: Why does SSR matter for SEO?
Google's crawler indexes pages in two waves: an immediate pass over the raw HTML, and a delayed, queued second pass where JavaScript actually executes. Social media preview bots often skip JavaScript entirely. SSR ensures both receive complete, indexable HTML on the very first request rather than depending on a JavaScript-rendering step that might be delayed or skipped.
Q: What is hydration in the context of SSR?
Hydration is the process where client-side JavaScript attaches event listeners and interactive behavior to HTML that the server already rendered, rather than building the entire page's DOM from scratch in the browser. It still requires downloading and running a JavaScript bundle comparable in size to a client-rendered app's.
Q: How is SSR different from static site generation?
Static site generation builds HTML once, at build time, and serves the identical file to every visitor, typically from a CDN for very fast delivery. SSR builds HTML fresh, on the server, for every single request, which allows it to include per-request or personalized data at the cost of added server-side computation and typically slower time-to-first-byte than a pre-built static file.
Q: What is incremental static regeneration (ISR)?
Incremental static regeneration is a Next.js rendering strategy that serves pre-built static HTML but automatically regenerates it in the background on a schedule or trigger, giving pages the delivery speed of static generation with periodically refreshed data instead of requiring a full rebuild for every content change.
Follow new articles
Add SciHub101 to your feed reader to see new science and technology stories.
About the Author
SciHub101 is an independent science and technology publication founded and edited by Buğra Sözeri, a software engineer and app developer based in Türkiye. AI tools assist with drafting and research. Source documentation in the existing archive is uneven, and articles are being reviewed and corrected. The Editorial Team byline identifies editorial responsibility; it does not certify specialist or independent human review. Where we compare products, anything built by our own team is labelled as such — see the editorial guidelines and About page for how corrections and disclosures work.
Related Articles




Zustand vs Redux — React State Management
Zustand vs Redux compared: bundle size, boilerplate, API, when to use each, plus how Jotai, Valtio, MobX, and TanStack Query fit in 2026.

What Is HTMX? Hypermedia for Modern Web
HTMX explained: how this 14KB library lets you build dynamic web apps with HTML attributes instead of a JavaScript framework, plus how it actually works.

Next.js vs React 2026 — Which Should You Learn First?
Next.js is a framework built on React, not a rival. What each does, Server Components, App vs Pages Router, and when to pick which, per the official docs.