Next.js at Scale: Patterns for 1M+ User Platforms
Caching layers, edge rendering and the boring architecture choices that keep pages under 300ms.
Performance at scale is rarely won in the framework. It is won in the decisions about what has to be dynamic, and the discipline to keep that list short.
Start by classifying every route: fully static, static with revalidation, or genuinely per-request. Most teams discover that the third category is far smaller than their current implementation assumes. Personalisation is usually a fragment of a page, not the page.
Push that fragment to the client or to a streamed boundary and the rest of the route becomes cacheable at the edge. This single reclassification is typically worth more than every micro-optimisation combined.
The second lever is the data access layer. Co-locating queries with components is ergonomic but invites waterfalls. We hoist the query plan for a route into one place, which makes the number of round-trips per render visible and therefore controllable.
The third is bundle discipline. Client components are load-bearing, and every one of them is a bet that interactivity is worth the shipped weight. Audit them the way you would audit dependencies.
None of this is exotic. The platforms that stay under 300ms at a million users are not running clever code; they are running a small amount of well-classified code.