Why static beats dynamic for 99% of sites

Most sites run a server, a database, and a runtime they never needed. The case for shipping cacheable HTML, and the few pages that earn a server.


The default architecture for a new website is wildly over-built. You reach for a server because the tutorial had one, a database because the framework assumed it, and a runtime that has to boot, query, render, and serialize on every request, all to return a page that hasn’t changed in three weeks. The machinery is real. The bill is real. The failure modes are real. The content is static.

Most of the web is documents. A blog post, a marketing page, a changelog, a docs site. These get read far more often than they get written and they’re identical for every visitor. When the output is the same for everyone and changes rarely, computing it fresh on every request isn’t flexibility, it’s waste with extra steps.

What static actually buys you

A static site is HTML, CSS, and a little JavaScript, generated once at build and served from a CDN edge. The substitution sounds small. The consequences aren’t. You trade per-request computation for build-time computation, and that single move collapses a whole category of problems.

No server to patch. No database to back up. No connection pool to exhaust. No N+1 query hiding behind a slow page. Your infrastructure is a bucket of files behind a cache, and the attack surface shrinks to almost nothing because there’s almost nothing to attack: no SQL to inject, no runtime to exploit, no secrets sitting in an environment waiting to leak.

Performance stops being a project. A cached file served from an edge node a few milliseconds from the user is about as fast as the web gets, and you get it by default rather than by heroics. The page a dynamic stack took 400ms to assemble arrives in 20ms because it was assembled once, weeks ago, and has been sitting there ready ever since.

The economics nobody mentions

Dynamic hosting is priced like a thing that’s awake. You pay for a process that has to be ready to respond, which means you pay whether anyone shows up or not. Idle capacity is still capacity and capacity is still a line item.

Static hosting is priced like storage and bandwidth, both nearly free at the scale a normal site operates. A personal site, a company blog, a documentation portal: these run on the free tier of half a dozen providers indefinitely, and the moment they get popular a CDN absorbs the traffic without you touching anything. The static cost curve stays flat where the dynamic one bends upward exactly when you’d least want it to, which is under load.

// "dynamic": run on every request, forever
app.get("/post/:slug", async (req, res) => {
  const post = await db.posts.findBySlug(req.params.slug);
  const html = await render(layout, post);
  res.send(html); // identical for every visitor, computed every time
});

// "static": run once at build, serve from the edge
for (const post of await db.posts.all()) {
  const html = await render(layout, post);
  await writeFile(`dist/post/${post.slug}.html`, html);
}

The dynamic version does that render forever. The static version does it once and walks away. Same output, wildly different bill.

When dynamic earns it

This isn’t an argument against servers, it’s an argument against reflexive ones. Some things genuinely have to be computed per request and pretending otherwise is its own kind of waste.

If the page is different for every user, a logged-in dashboard, a personalized feed, a cart, you need dynamic rendering and there’s no clever way around it. If the data changes by the second and staleness is unacceptable, live prices, live scores, live availability, a cache won’t save you. And if the core of the product is the computation, a search engine, an editor, a simulator, then the server isn’t incidental, it’s the thing you’re selling.

The honest test is one question: does this page change based on who is asking or when they ask? If the answer is no, it should be a file. The mistake isn’t using dynamic rendering. It’s using it for the 99% of pages that are documents wearing a server costume.