ostr.io vs SSR
Dynamic rendering vs SSR - which one should you ship?
Dynamic rendering (pre-rendering for crawlers) vs server-side rendering: cost, complexity, SEO outcomes, and when to pick each approach.
Updated
Choose ostr.io if
- Crawler traffic is a meaningful share of total hits and you want to isolate its cost.
- You run a mature SPA (React, Vue, Svelte, Angular) that SSR migration would rewrite from the ground up.
- You want a hybrid route model where only freshness-critical URLs keep SSR.
- You need framework-independent rendering — multiple frontends behind one domain.
SSR might work if
- You are starting a new Next.js / Nuxt / SvelteKit app and SSR is the framework default.
- Content is personalized per-user and cannot be cached meaningfully.
- The same HTML must stay real-time for both users and crawlers on the URLs that matter most.
- Your team is already paying for SSR infrastructure and crawler traffic is low (< 5%).
Dynamic rendering vs SSR — side by side
Both approaches produce crawlable HTML. Dynamic rendering separates the rendering concern from the user-facing runtime; SSR couples them inside the framework.
Dimension | BestDynamic rendering | Server-side rendering |
|---|---|---|
| Framework coupling | Framework-agnostic | Tied to framework runtime |
| Cost model | Fixed per-tier | Per-request compute |
| Cold start | None (pre-rendered) | 200-600ms lambda cold start |
| Content freshness | Cache TTL bounded | Real-time per request |
| Personalization | Crawler-facing only | Full per-user logic |
| Migration cost | Middleware snippet | Framework migration |
| Crawler-traffic cost isolation | Isolated in cache | Hits origin every time |
| Hybrid deployment fit | Easy to apply by route class | Possible, but less flexible |
| AI crawler readiness | Stable crawler-facing HTML | Depends on runtime cost tolerance |
| Greenfield developer experience | Best for existing apps | Best when chosen from day one |
| Route-level personalization | Limited to crawler-facing cache | Full request-time logic |
A 3-question decision framework
First: is the content the same for every visitor? If yes, dynamic rendering is nearly always cheaper and simpler. If content is user-personalized, SSR or CSR with hydration is the fit. Teams still deciding where that line sits should compare this page with ostr.io vs Vercel SSR.
Second: is the crawler traffic budget predictable? If crawler volume spikes after a sitemap push or AI crawler discovery, pre-rendering isolates the cost. SSR makes crawler volume directly visible on your origin bill, which is why JavaScript rendering cost matters here.
Third: is framework migration a blocker? If rewriting the SPA to SSR would take months, dynamic rendering is the pragmatic layer that unlocks SEO without a rewrite.
Decision tree by content type
Use SSR when the route must compute user-specific state before the first byte: account dashboards, private pricing, checkout, geo-sensitive availability, or pages where auth changes the main content. Use dynamic rendering when the crawler only needs stable public HTML: marketing pages, documentation, changelogs, category pages, public listings, and long-tail content archives.
The catch is that most sites are mixed estates, not pure examples from framework docs. A SaaS app can have authenticated dashboards, public docs, changelogs, and marketing pages on one domain. In that situation the right answer is usually route classification, not a platform-wide ideological choice. That is also why SaaS and ecommerce teams often end up with a hybrid model.
Most mature sites run both
The typical mature stack is: SSR or ISR for the top 1% of pages (homepage, top categories, top product pages) + dynamic rendering for the long tail. This lets teams optimize freshness where freshness matters and cost where it does not. That split is especially common on SaaS and ecommerce stacks.
The two layers do not conflict. Dynamic rendering's bot-detection middleware simply forwards bot traffic past the SSR layer to the pre-rendered cache.
In practice, teams that keep this split explicit make better trade-offs. They know which URLs earn the cost of real-time rendering and which URLs only need clean, indexable HTML on first fetch. Once that rule exists, crawler economics stop leaking into every framework decision.
Where SSG and ISR fit in the same landscape
SSG is the cleanest answer when the content graph is small, stable, and cheap to rebuild. ISR extends that model when the graph is still manageable but changes often enough that full rebuilds become painful. Dynamic rendering enters when the site is already client-rendered, when the URL graph grows faster than rebuild logic can handle, or when crawler-cost isolation matters more than framework purity.
ISR sits closer to SSR than to dynamic rendering because the first request after expiry still depends on application runtime. That matters for cost modeling. If the route is revisited by crawlers far more often than by humans, ISR still pushes bot demand onto origin infrastructure. Dynamic rendering removes that pressure by serving a crawler-facing cache instead.
The real decision is cost over time, not page-speed ideology
Teams often frame this as a philosophical debate about rendering models. In practice it is a budget and operations decision: which requests must be real-time, and which requests only need stable crawler-facing HTML? Once the URL graph grows, that question matters more than purity.
If the site is moving toward 100k+ URLs, pair this page with large sites (100k+ pages). If the concern is build-vs-buy at the edge, pair it with ostr.io vs Cloudflare.
Freshness, cost, and migration effort rarely line up neatly. SSR usually wins on freshness, dynamic rendering usually wins on migration speed for an existing SPA, and the long-tail cost curve usually favors dynamic rendering once crawler demand becomes material. The right architecture depends on which constraint hurts first.
When each model is the wrong fit
Dynamic rendering is the wrong fit when the important indexed HTML is personalized at request time or when parity between the live app and crawler snapshot cannot be kept stable. SSR is the wrong fit when crawler traffic forces the application layer to do expensive work on pages that do not need per-request computation for real users.
Worth noting: many bad architecture decisions come from choosing too early and applying the choice too broadly. If the app is already live and SEO is blocked now, dynamic rendering often buys time and visibility first. If the app is greenfield and built around public, freshness-critical routes, SSR may be the cleaner starting point.
Cloaking policy - dynamic rendering is still allowed
Google's dynamic rendering documentation has been stable since 2018. Serving substantially the same content to bots and users is the defining line; manipulating rankings by showing different content is cloaking.
The practical rule is: if a user disables JavaScript and sees the same text, headings, prices, reviews and structured data that the pre-rendered snapshot contains, the site is on the correct side of the line. For implementation-level details, follow pre-render cache headers and parity checks in the advanced guides.
Hybrid: SSR for top pages + dynamic rendering for long tail
Common pattern in production. Keep SSR for routes that need freshness, delegate the rest to a pre-rendered cache.
import { NextResponse } from "next/server";import type { NextRequest } from "next/server";const BOT_REGEX = /bot|crawler|spider|googlebot|bingbot|applebot|gptbot|claudebot/i;const SSR_ROUTES = /^\/(?:|products|cart|checkout)$/;export function middleware(req: NextRequest) { const ua = req.headers.get("user-agent") ?? ""; const isBot = BOT_REGEX.test(ua); const isFresh = SSR_ROUTES.test(req.nextUrl.pathname); // Human users: SSR for everything, no middleware changes if (!isBot) return NextResponse.next(); // Bots on freshness-critical routes: keep SSR if (isFresh) return NextResponse.next(); // Bots on the long tail: forward to pre-rendered cache const render = new URL( `https://render.ostr.io/render?url=${encodeURIComponent(req.nextUrl.toString())}`, ); return NextResponse.rewrite(render);}export const config = { matcher: "/((?!_next|api|og|static).*)" };SSR vs ostr.io — questions engineers ask
No, as long as the pre-rendered HTML is substantially the same as the hydrated page. Google's documentation explicitly lists dynamic rendering as an accepted technique.
No. SEO outcomes depend on what reaches the crawler, not how it was generated. A well-configured dynamic rendering layer produces identical crawler-facing HTML to an SSR-rendered page, with lower origin cost.
Yes. Most mature sites do: SSR for the top 1% of pages where freshness matters, dynamic rendering for the long tail. The bot-detection middleware chooses the path per request.
SSG (static generation at build time) is the cheapest path when the content graph is small and changes infrequently. Once the content graph exceeds a few thousand pages or changes more than once a week, SSG build times and deploy complexity push teams toward SSR or dynamic rendering.
Classify routes by two tests: does the HTML need per-user or per-request freshness, and does the route receive material crawler demand? Keep SSR where both answers are yes. Use dynamic rendering where the HTML is public and stable enough to cache for crawlers.
It is still relevant in 2026 because many production estates are mixed: legacy SPA sections, newer SSR sections, docs, marketing pages, and crawler-heavy long tails on one domain. Dynamic rendering remains the fastest way to make the crawler-facing layer stable without rewriting the whole estate.
For public long-tail routes with heavy crawler traffic, dynamic rendering is usually cheaper because it isolates bot demand in cache. For a small set of freshness-critical routes, SSR can be the better trade because the same runtime serves both users and crawlers.
Yes. Google Web Rendering Service (WRS) consumes whatever HTML the URL returns. It does not distinguish between "SSR-produced HTML" and "snapshot-produced HTML." What matters is that the HTML is complete and stable.
Related comparisons and guides
Compare — pre-rendering vendors
Eight head-to-head vendor comparisons for the dynamic rendering layer.
ostr.io vs Vercel SSR
Concrete cost comparison between SSR and pre-rendering.
Guide — JavaScript rendering cost
Headless browser budget across 10k / 100k / 1M URLs.
Guide — large sites 100k+
Scale playbook where SSR cost starts to hurt.
Use case — SaaS
Common SSR + dynamic rendering hybrid.
Use case — ecommerce
Where freshness vs cost trade-offs show up fastest.
Editorial trust
Written by ostr.io engineering team · Engineering Team. We build and run pre-rendering infrastructure for more than 200 engineering teams, which is where the numbers and code samples on this page come from.
Last updated . Editorial scope and review policy: About prerender.info.
Run this comparison against your own stack
prerender.info · pre-rendering for JS SEO