Performance 10 min read

Next.js Performance: ISR, Streaming, and Partial Prerendering

By Born Digital Studio Team Malta

Next.js has evolved from a straightforward React server-rendering framework into a sophisticated platform with multiple rendering strategies that can be mixed within a single application. The challenge is no longer "can Next.js be fast?" but rather "are you using the right rendering strategy for each part of your application?" Choosing between static generation, incremental static regeneration, server-side rendering, streaming, and the emerging partial prerendering model has a profound impact on both performance and infrastructure cost. This guide breaks down when to use each approach and how to configure them for optimal results.

Incremental Static Regeneration in the App Router

ISR lets you serve statically generated pages while revalidating them in the background at a configurable interval. In the App Router, ISR is controlled through the revalidate option on fetch calls or the route segment config. Setting revalidate to 60 means the page is served from cache for 60 seconds, then the next request triggers a background regeneration while the stale page continues to be served. This gives you the performance of static generation — sub-100ms Time to First Byte from the CDN edge — with content freshness measured in seconds rather than requiring a full rebuild.

The key to effective ISR is choosing the right revalidation interval for each route. Product listing pages that update frequently might use a 30-second interval, while marketing pages that change weekly can use 86400 seconds (one day). For content that must be fresh immediately — inventory counts, pricing — use on-demand revalidation triggered by a webhook from your CMS or commerce platform via the revalidatePath or revalidateTag APIs. This gives you instant cache invalidation without the overhead of server-rendering every request.

Streaming SSR and Suspense

Traditional server-side rendering has a fundamental bottleneck: the server must complete all data fetching and rendering before sending any HTML to the browser. Streaming SSR, built on React Suspense, breaks this constraint by sending HTML in chunks as each component resolves.

  • Faster Time to First Byte: The shell of the page — header, navigation, layout — streams immediately while slow data fetches resolve in parallel. Users see a meaningful page structure within milliseconds rather than waiting for a complete server response.
  • Progressive hydration: Components hydrate independently as their HTML arrives, so interactive elements near the top of the page become usable before the entire page has finished streaming. This directly improves INP by reducing the total blocking time of hydration.
  • Graceful loading states: Wrap slow components in Suspense boundaries with fallback skeletons. The loading.tsx convention in the App Router automatically creates Suspense boundaries at the route segment level, giving you streaming with zero additional configuration.

Partial Prerendering

Partial Prerendering (PPR) represents the convergence of static and dynamic rendering within a single route. With PPR, the static shell of a page — layout, navigation, product description — is prerendered at build time and served from the CDN edge, while dynamic holes — personalised recommendations, real-time pricing, cart state — are streamed in from the server. The static shell arrives instantly, and dynamic content fills in progressively via Suspense boundaries.

This is transformative for eCommerce because it eliminates the traditional trade-off between personalisation and performance. A product page can have a sub-50ms TTFB for the static content while still rendering personalised sections server-side. To enable PPR, set the experimental.ppr option in next.config.js and ensure your dynamic content is wrapped in Suspense boundaries. The static portions are determined automatically: any component that does not access dynamic functions like cookies(), headers(), or uncached fetch calls is eligible for prerendering.

Caching Strategy and the Data Cache

Next.js employs multiple cache layers — the Router Cache, Full Route Cache, Data Cache, and Request Memoization — and understanding how they interact is essential for both performance and correctness.

  • Data Cache: Fetch responses are cached by default in the App Router. Use the next.revalidate option to control staleness at the individual fetch level, giving you granular control — a product's description might cache for hours while its inventory status caches for seconds.
  • Cache tags for surgical invalidation: Tag your fetch calls with semantic labels and use revalidateTag to invalidate specific data across all routes that consume it. When a product price changes, invalidate the "product-123-price" tag rather than regenerating every page that displays that product.
  • Router Cache awareness: The client-side Router Cache can serve stale data to users navigating between pages. Set appropriate staleTimes in your configuration and use router.refresh() after mutations to ensure users see fresh content after actions like adding items to their cart.

Bundle Optimisation and Server Components

React Server Components, the default in the App Router, render entirely on the server and send zero JavaScript to the client. This means a complex product description section with rich formatting, data transformations, and conditional logic adds zero bytes to your client bundle. Reserve the "use client" directive for components that genuinely need interactivity — form inputs, dropdowns, carousels, and accordions. Audit your client components regularly to ensure interactivity has not crept into components that could be server-rendered. Use the Next.js bundle analyser (@next/bundle-analyzer) to identify unexpectedly large client modules and refactor them to server components where possible.

Born Digital builds high-performance Next.js applications for eCommerce and digital platforms. We help teams adopt advanced rendering strategies — ISR, streaming, and partial prerendering — to deliver fast, personalised experiences without compromising on developer productivity or infrastructure cost.

Need help with performance?

Born Digital offers expert performance services from Malta.

Share this article

Help others discover this insight

Born Digital Studio Team

Born Digital Studio is a Malta-based digital engineering studio specialising in eCommerce, blockchain, and digital product development. We build high-performance platforms for businesses across Europe.

Have a project in mind?

If this topic resonates with your business challenges, let's talk about how we can help.