· 4 min read ·

Stop Confusing Dynamic Web Pages With SSR

Dynamic content and server-side rendering are not the same thing. Mixing them up is why people over-engineer sites that Cloudflare's free tier could serve perfectly.

Listen to article
0:00 / 0:00

Your site fetches data from an API. The content updates. You’ve decided this means you need SSR. You are wrong, and this mistake is costing you complexity you don’t need.

Dynamic content and server-side rendering are not the same thing. Conflating them is how people end up running full SSR frameworks on sites that a static host and a fetch call could serve perfectly.

Dynamic and SSR are not synonyms

Server-side rendering means the server builds the HTML for each request at the moment it arrives. The user hits the URL, your server runs code, assembles the page, and ships it down the wire. The output is HTML, generated live, every time.

Dynamic content means the data on your page changes. That’s it. It says nothing about when the HTML gets built, or where.

These are orthogonal. A page can be statically generated at build time and still show live data — the static shell loads instantly, then JavaScript fetches the fresh numbers and drops them in. A page can be server-rendered and show the same content to every visitor for a week. The axis isn’t static versus dynamic. The axis is when the HTML is assembled: at build time, at request time on a server, or at request time in the browser.

Most people reaching for SSR need the third option. They’re calling it the second by accident.

What Cloudflare actually gives you

Cloudflare Pages is a CDN for static files. You push a build, it lands on hundreds of edge nodes, and your pages load from wherever the visitor is closest. No server, no per-request compute, no cold starts. The monthly bill for a portfolio or a marketing site is zero.

The part people miss: you can still talk to live data. Your static page can call a Cloudflare Worker — a small function that runs at the edge — and that Worker can hit your database, call an external API, or compute anything you need. The response comes back to the browser, JavaScript writes it into the page, and the visitor sees fresh data.

This is not a compromise. For most sites this is the right architecture. The HTML is prebuilt and cached globally, so it’s fast. The data layer is a Worker endpoint, so it’s flexible. Nothing about this requires a full SSR framework.

When SSR is actually the answer

SSR earns its complexity in two situations.

The first is SEO-critical pages where the content changes per-request and has to be in the HTML when the crawler arrives. Product listings that vary by user, search results that need to be indexed — these need the rendered HTML ready at request time, not assembled in the browser after a fetch.

The second is when your page is so data-dense, with so many dependent calls, that assembling it in the browser means visible loading states the user shouldn’t have to see. A dashboard with twenty data sources might genuinely be better rendered on the server.

Notice what’s not on that list: “my site fetches some data.” That’s not SSR territory. A GitHub stats card that loads after the page is fine. A pricing section that calls a Worker to get the current numbers is fine. The live data on snazzie.space — GitHub contributions, Cloudflare traffic stats — arrives over a Worker API after the static page loads. It doesn’t need SSR. It needs a fetch call.

The cost of the wrong call

Over-reaching for SSR isn’t free. You’ve traded a static site — which deploys in thirty seconds, has no server to patch, and never cold-starts — for a runtime that has to be managed, scaled, and kept alive. Cloudflare Workers can do SSR through their compatibility with frameworks like Astro in hybrid mode, but the moment you do that, the simplicity you signed up for is gone.

The billing changes too. A static site on Cloudflare Pages costs nothing under reasonable traffic. An SSR deployment that handles your fetch-at-the-edge needs differently — generating HTML on every request — starts burning Worker invocations. At low traffic this is still cheap. But you’re paying a real cost for something you didn’t need.

The right question to ask

Before reaching for SSR, ask where the HTML needs to be ready. If it needs to be crawlable and personalised before JavaScript runs: SSR. If it needs live data but SEO doesn’t depend on that data landing in the initial HTML: static site plus a fetch call.

Most sites asking the question belong in the second bucket. Build it statically, host it on Cloudflare Pages for free, put any server logic in a Worker. The data comes in after load, the page is globally cached, and you’ve spent nothing.

Dynamic is not a synonym for SSR. It never was.