Static generation vs server-side rendering: how to choose
Static generation builds pages once at build time, server-side rendering builds them on every request. Here is how to choose between them.
Every web page has to be turned into HTML at some point. The real question is when that happens: before anyone visits, or at the moment someone asks for the page. That single choice affects speed, cost, freshness and what your hosting needs to look like.
The two approaches
Static generation builds the HTML ahead of time, during the build. The result is a set of ready-made files that can be served instantly from a CDN. Nothing is computed when a visitor arrives.
Server-side rendering builds the HTML on a server for every request. The server can read cookies, query a database and return a page that is different for each visitor, at the cost of doing work on every visit.
There is also client-side rendering, where the browser receives a small HTML shell and builds the page with JavaScript. It suits highly interactive apps, but it gives search engines and slow devices more work to do.
Side by side
| Static generation | Server-side rendering | |
|---|---|---|
| When HTML is built | At build time | On each request |
| Speed for the visitor | Very fast | Depends on the server |
| Data freshness | As of the last build | Always current |
| Personalised pages | Not by itself | Yes |
| Hosting cost | Low | Higher, needs a running server |
How to choose
Ask three questions about each page:
- Is the page the same for every visitor? If yes, static generation is usually the right choice.
- How often does the content change? If it changes a few times a week, rebuilding on each change is fine. If it changes every second, you need rendering at request time or client-side updates.
- Does it depend on who is logged in? If yes, use server-side rendering or load the personal parts in the browser.
A blog, a documentation site and a portfolio all fit the first case. A dashboard or a shopping cart does not.
A middle ground
Frameworks such as Next.js let you mix approaches page by page. They also let you refresh static pages on a schedule or on demand, so you keep the speed of static files for content that changes occasionally.
How this blog does it
Every article here is generated at build time. The route lists all posts up front and refuses any URL that is not in that list:
export const dynamicParams = false;
export function generateStaticParams() {
return getAllPosts().map(({ section, subsection, slug }) => ({
section,
subsection,
slug,
}));
}Publishing a new article means pushing a commit, which triggers a new build. For a personal blog that is a good trade: pages load instantly and hosting stays simple.
Takeaway
Default to static generation whenever a page is the same for everyone. Reach for server-side rendering only where a page truly needs fresh or personal data. Choosing per page, instead of for the whole site, gives you the speed of the first and the flexibility of the second.