Skip to content
Engineering

CSR vs SSR vs Prerendering, Pick the Render Strategy

BYOB Team

BYOB Team

7 min read

Prerender marketing and docs pages for fast static delivery with consistently quick time to first byte. Use SSR when each request needs fresh, user specific HTML. Use CSR shells only behind login where SEO matters less. In SvelteKit you mix strategies per route with prerender, ssr, and csr page options, but watch hydration cost on every server rendered page.

Key takeaways

  • • Prerender static marketing and docs for speed, SEO, and edge caching
  • • Use SSR per request for fresh authenticated HTML at the cost of server work
  • • Reserve CSR shells for login walled app areas where crawlers never go
  • • Mix per route in SvelteKit and budget hydration like money
CSR vs SSR vs Prerendering, Pick the Render Strategy

Short answer, match rendering to freshness need #

Prerender pages that look the same for everyone until the next deploy: landing pages, pricing, docs, marketing content. Fast delivery, crawler-friendly HTML, edge caching essentially free.

Use server-side rendering per request when HTML depends on the user, session, or fresh data: dashboards, account pages, personalized feeds. Correct content per visitor, at the price of server work on every hit.

Use client-side rendering as a shell sparingly, mostly behind login where SEO pressure drops and interaction density justifies a client boot.

This post is a decide/compare guide to picking prerender, SSR, or CSR per SvelteKit route. If you want the learn/define concept instead — what prerendering is and which pages to keep dynamic — see What Is Prerendering.

In SvelteKit you never pick one globally. You mix per route, and the framework gives you three switches to do it.


flowchart TD A[Request hits SvelteKit route] --> B{Need fresh per-user HTML?} B -->|No: same for everyone| C[Prerender at build, cache at edge] B -->|Yes: user/session data| D[SSR per request] B -->|Behind login, heavy interaction| E[CSR shell + hydration] C --> F[Instant HTML, SEO friendly] D --> G[Correct per-visitor HTML, costs server work] E --> H[Boot JS, fetch inside app]

What does each strategy do? #

A CSR shell ships near-empty HTML plus JavaScript, then renders in the browser. Flexible for app-like interaction. Weak for first paint and indexing, because content arrives only after scripts download, parse, and execute. As the page grows, so does the bundle, and mobile users feel every kilobyte.

SSR per request renders full HTML on the server for every visit, then hydrates it into an interactive app. Crawlers and visitors get real content immediately. The server pays per request: compute time, data fetching, slower time to first byte under load.

Prerendering computes HTML at build time and saves static files. Same benefits as server pages for readers, zero per-visitor compute, deployable to plain CDNs. The tradeoff is staleness by design. Content updates only when you rebuild, and generating a file per URL gets painful for huge personalized sitemaps.

Hydration connects server HTML to client interactivity. Components initialize with the data the server already fetched, event listeners attach, the page wakes up. The web.dev rendering guide states the core warning plainly: server-rendered pages can appear loaded while remaining unresponsive until client scripts execute, which on mobile can frustrate users staring at a dead page, as stated by Osmani and Miller (rendering on the web).

Think of it like a restaurant. Prerendering is meal prep, cooked once, served instantly. SSR is cooking to order, fresh every plate, slower under a rush. CSR is handing over ingredients with a recipe card.


Comparison table #

Criterion Prerendering SSR per request CSR shell
Freshness Deploy-time Request-time Client-time after fetch
SEO friendliness Strong Strong Weak without extra work
Server cost Lowest Highest Low, data via APIs
First paint Fast Fast HTML, needs hydration Slower, waits on JS
Time to first byte Consistently fast Slower under load Fast shell, slow content
Personalization None natively Native After client fetch
Best fit Marketing, docs Dashboards, accounts Authenticated app shells

Read rows as tradeoffs. Speed and cacheability pull against freshness and personalization, and no strategy wins every row.


How does SvelteKit routing work in practice? #

SvelteKit renders components on the server first and sends HTML to the client, then hydrates and hands subsequent navigation to a client router, with per-page control through exports from page, layout, or server modules, as stated in the SvelteKit docs (page options).

Three exports run the show:

js
// src/routes/marketing/+page.js
export const prerender = true;
js
// src/routes/dashboard/+page.js
export const prerender = false;
export const ssr = true;
js
// src/routes/app/settings/+page.js
export const ssr = false; // client shell behind login

Layouts pass defaults downward and pages override them, so you can prerender the whole marketing section from one layout file while keeping dashboards dynamic. Routes marked for prerendering leave the dynamic server manifest, which shrinks serverless and edge functions, as stated in the SvelteKit docs (page options).

The glossary adds the mental models. Prerendering scales nearly free per visitor since files serve from CDNs, while SSR avoids the extra round trips of client-only apps and keeps pages usable when JavaScript fails, as stated in the SvelteKit docs (glossary). The same glossary warns that single-page apps serving empty shells carry large performance and SEO impacts, recommended only for narrow cases like wrapped mobile apps, as stated in the SvelteKit docs (glossary).

One classic mistake: prerendering a route that secretly depends on cookies or authorization headers. The build succeeds, every visitor sees identical HTML, and access control looks broken. The rule is strict. For a page to be prerenderable, any two users hitting it directly must get the same content from the server, as stated in the SvelteKit docs (page options). Personalized data belongs in client fetches after load, or the route belongs in SSR.

Pages with form actions cannot be prerendered either, since a server must handle the posts. And disabling both ssr and csr renders nothing at all, which the docs flag with justified alarm.


Try it: Sitemap Generator

Try it right here: sitemap generatorOpen full tool

Loading the interactive tool… or open it here.

How does SEO differ across the three? #

Google processes JavaScript pages in three phases, crawl, render, then index, running scripts with an evergreen Chromium, as stated in the Google docs (JavaScript SEO basics). Client rendering can work. It often takes longer to be indexed, needs extra testing, and leans on workarounds like dynamic rendering for heavy architectures, as stated by the web.dev guide (rendering on the web).

So the SEO ranking is not close. Prerendered and server HTML arrive complete for any crawler, including the limited ones. Client shells gamble on every bot executing JavaScript correctly and patiently. Public content should never take that bet.


Hydration and performance discipline #

Server HTML alone does not make an app fast. After markup arrives, the framework downloads, parses, and executes JavaScript to attach interactivity, and that bill lands on the main thread.

Keep it small. Ship less JavaScript on content routes, defer non-critical components, avoid deep client-only trees above the fold, and measure time to interactive on real mobile hardware instead of a desktop with fiber. Aggressive code splitting and lazy loading are the standard prescription for bundle-heavy experiences, as stated by Osmani and Miller (rendering on the web).

Static-first public pages plus lean SSR for authenticated pages is a durable default. Crawlers and visitors get fast content, server work concentrates where personalization justifies it, and CSR shells stay quarantined behind login walls.


What we learned building this #

In BYOB we set render choice per route with framework page options. Marketing, blog, and tool routes stay prerender friendly while dashboard and API routes stay server rendered. This mix is documented in the how BYOB uses SvelteKit guide and matches the short answer in the post: use prerender where content is same for everyone and server rendering where it must reflect the user.

Who this is for (and who should skip it) #

This fits SvelteKit teams choosing how each route should render. If you run a mix of marketing pages plus authenticated dashboards you will use more than one strategy and this shows where each earns its keep.

Skip fine tuning if your site is a few static pages with no login. Prerender everything and move on until fresh per user HTML becomes a real requirement.

  • Best for developers choosing render modes across marketing plus dashboard routes.
  • Best for startups mixing static pages with logged in views.
  • Best for beginners prerendering a few pages before adding dynamic needs.

Verdict, static by default and dynamic on purpose #

Prerender what rarely changes. Server-render what must be fresh and personal. Client-render only the shells where login walls remove SEO pressure and interaction density earns a boot.

For most builder-style sites, landing page plus app, that means static marketing, SSR dashboards, and no global client takeover. Let each route earn its strategy from freshness, SEO, and hydration evidence. Measure the bottlenecks first, as the rendering guide advises, then pick the cheapest strategy that survives contact with your constraints.

How we picked these

Compared rendering claims to SvelteKit page options, glossary, Google SEO, and web.dev articles; no render benchmarks were run.

Frequently asked questions

What is prerendering?

Prerendering computes page HTML at build time and saves it as static files. It suits content identical for every visitor until the next deploy, and any two users hitting the page directly must receive the same server content

When does SSR beat prerendering?

When HTML must reflect the current user, permissions, or live data. SSR generates full HTML per request, trading static speed and cheap caching for freshness

What is hydration cost?

Hydration is the client JavaScript work that attaches interactivity to server HTML. Large bundles delay input response, and a page can look ready while remaining dead to clicks until hydration finishes

How does Google handle client rendered pages?

Google runs JavaScript with an evergreen Chromium in crawl, render, and index phases, but client only content often takes longer to be indexed, so server HTML remains the safer SEO bet

Changelog

  • • Added fit guide, comparison table, and hands on notes
  • • Intent split 2026-09-23 - decide/compare lane three-way plus early cross-link to what-is-prerendering

About the Author

BYOB Team

BYOB Team

The creative minds behind BYOB. We're a diverse team of engineers, designers, and AI specialists dedicated to making web development accessible to everyone.

Ready to start building?

Join thousands of developers using BYOB to ship faster with AI-powered development.

Get Started Free