Skip to content
McGinnPublishing
Architecture

Stop asking what framework you use. Write down what renders where.

The most consequential decision in a headless build is made once, early, and almost never revisited. It is also the one most often left to the defaults.

7 min readNiamh McGinn, Founder & Technical Director

Ask a team which rendering strategy a route uses and you will usually get an answer about the framework. Ask them why and you will get a shorter answer. On the projects we inherit, the rendering strategy is almost always an artefact of defaults rather than a decision anyone made.

Four strategies, and the default is wrong three times

Next.js gives you a small number of genuinely different strategies, and choosing between them is a product decision disguised as a technical one.

  • Static — built once, served from everywhere. Correct for anything whose content changes on a human timescale and whose output is identical for every visitor.
  • Incremental — static, revalidated on a schedule or on a publish webhook. Correct for anything an editor changes, including most commerce catalogues.
  • Dynamic — rendered per request. Correct for search, account, basket, anything personalised.
  • Streaming dynamic — shell rendered fast, slow parts deferred. Correct for long-form pages assembled from many CMS queries.

The failure mode is asymmetry. Over-server-rendering costs you latency and origin load; under-server-rendering costs you correctness. Teams are anxious about the second and complacent about the first, which is how you end up paying a database round trip on every view of a page that has not changed since Tuesday.

Write an ADR

We write one short architecture decision record per route group. Four sections: context, decision, consequences, revisit trigger. Here is a real one, abbreviated:

## ADR-014: Product and category pages

Status:  accepted · 2025-04-02

Context
  Catalogue pages are viewed by anonymous traffic at a ratio of
  roughly 400:1. Prices and stock change without notice. Pages
  must be present in search results within minutes of a price
  change, not hours.

Decision
  Generate statically at build. Revalidate on tag with a
  5-minute stale-while-revalidate window. Shopify webhooks
  revalidate the affected product tags immediately; the
  window exists only for missed webhooks.

Consequences
  Origin load drops by ~94%. Price propagation is bounded at
  5 minutes by design, 30 seconds in practice via webhook.
  Search index must not crawl the variant URLs.

Revisit if
  Catalogue exceeds 500k SKUs, or variant-level pricing
  becomes per-visitor (at which point this is a session
  problem, not a rendering one).

That document takes fifteen minutes to write and saves the argument three times. It also makes the platform transferable: any engineer can read fourteen short records and understand why the site is fast.

A rendering decision nobody wrote down is a rendering decision nobody will defend when the origin starts falling over.

Revisit triggers matter more than the decision

Every ADR above should say what would make it wrong. Without that, decisions calcify and your platform drifts out of contact with its own constraints. With it, the review conversation starts from evidence instead of memory — which is also the only way a decision made by someone who has since left the studio can be revisited at all.

Tagged

  • Rendering
  • ISR
  • Architecture
  • Performance