DEV Community

Cover image for Rendering in Next.js: Lessons from High-Traffic Production Apps 🚀
Jagraj Bains
Jagraj Bains

Posted on • Originally published at techexploration.hashnode.dev

Rendering in Next.js: Lessons from High-Traffic Production Apps 🚀

Next.js is popular for its hybrid rendering capabilities – from Server-Side Rendering (SSR) and Static Site Generation (SSG) to Incremental Static Regeneration (ISR) and classic Client-Side Rendering (CSR). Modern engineering teams have leveraged these strategies to optimize performance, SEO, and user experience. Let’s breakdown how engineering teams around the world are making their rendering decisions when using Next.js.

But first, we’ll go through a refresher on the buzzwords surrounding these rendering strategies. We’ll compare them in pages vs app router setups.

Overview: SSR, SSG, ISR, and CSR in a Nutshell

Rendering Intent Pages Router App Router When to Use
Client-Side Rendering (CSR) useEffect + fetch on client use client components + client fetch Highly interactive UIs, dashboards, editors
Server-Side Rendering (SSR) getServerSideProps fetch(..., { cache: 'no-store' }) or export const dynamic = 'force-dynamic' User-specific data, real-time content
Static Site Generation (SSG) getStaticProps Default behavior (fetch is cached) Marketing pages, blogs, docs
Incremental Static Regeneration (ISR) revalidate in getStaticProps export const revalidate = 60 Product pages, content that updates periodically
On-Demand Revalidation res.revalidate() revalidatePath() / revalidateTag() CMS-driven updates, price/content changes
Hybrid (Static + Dynamic) Mix of getStaticProps or getServerSideProps with fetch on client Server Components + selective use client Most real-world apps
Streaming / Partial Rendering Not available Suspense + Server Components Faster perceived loads for large pages
Edge Rendering config.runtime = 'edge' export const runtime = 'edge' Low-latency global apps. Middlewares, geo-location based routing and auth checks.

When you’re new to Next.js, the instinct is usually to pick one rendering strategy and apply it everywhere. Blogs? Easy — SSG. Product pages? ISR sounds perfect. It feels clean, consistent, and “architecturally correct.”

But once you start working on real production problems, that mental model breaks down.

In practice, most production apps end up being hybrid. Teams use SSG or ISR for SEO-critical, mostly stable content, and layer in SSR or CSR only where freshness or personalization truly matters. Trying to solve everything with a single strategy almost always leads to either stale data, unnecessary server load, or both.

Next.js App Router Note:

In Next.js 13+ with the App Router, the lines between SSR, SSG, and ISR blur a bit. The framework by default will cache fetch requests during server rendering, treating them as static unless told otherwise. Developers now configure rendering behavior via caching directives (e.g. export const revalidate = 60 for ISR, or export const dynamic = "force-dynamic" to disable caching). Essentially, the App Router gives fine-grained control: you can have static segments and dynamic segments in the same page. React Server Components (RSC) further change the game – by default, components are rendered on the server without sending JavaScript to the client unless they need interactivity. This means you can achieve the effect of SSG/SSR (pre-rendered HTML) for much of the UI, while only shipping JS for interactive parts. The result is better performance (less JS to parse) without sacrificing dynamic capabilities. Keeping these mechanisms in mind, let’s quickly understand the core web vitals that would be affected with the rendering strategies.

Overview of CWV (Core Web Vitals)

Metric What it Measures Simple Definition Why It Matters
LCP (Largest Contentful Paint) Loading performance Time taken for the main visible content (hero image, headline, large card) to appear on screen Directly affects perceived speed and SEO. Users decide quickly if a page feels fast or slow.
TTFB (Time to First Byte) Server responsiveness Time between a request and the first byte of HTML received from the server High TTFB usually means slow backend, heavy SSR, or no caching. Impacts all other metrics.
FCP (First Contentful Paint) Initial visual feedback Time until any content (text/image) appears on screen Indicates when users stop seeing a blank page. Short FCP times affects perceived speed as well.
CLS (Cumulative Layout Shift) Visual stability How much the page jumps around while loading Layout shifts break user trust and hurt conversion (e.g., clicking wrong buttons).
INP (Interaction to Next Paint) Interactivity & responsiveness How quickly the UI responds after a user interaction (click, tap, input) Replaces FID. Measures real-world responsiveness, critical for apps and dashboards.
FID (First Input Delay) (deprecated) Initial interaction delay Delay between first interaction and browser response Being phased out in favor of INP (still seen in older audits).
Hydration Time Client-side readiness Time taken for React to attach event handlers after HTML loads Slow hydration = UI looks ready but feels broken or unresponsive.
JS Execution Time Main thread load Time spent running JavaScript on the browser Heavy JS blocks rendering and interactions—common in CSR-heavy apps.
Render Blocking Resources Load prioritization CSS/JS that blocks the page from rendering Poor handling delays FCP/LCP and worsens perceived speed.

With that out of the way we can move to the findings.

The Streaming Giants: Netflix and Hulu's Path to SSR Excellence

Netflix transitioned from a Java-based architecture where the server generated markup for the entire page—often forcing users to wait for content they would never see—to a Next.js 15 "Edge-First" philosophy. By utilizing Streaming SSR and Hybrid React Server Components, Netflix reduced its average server render time to just 23ms. Critical "above-the-fold" content is delivered instantly, while non-critical segments are wrapped in React Suspense boundaries and streamed to the client.

This shift delivered massive improvements in Core Web Vitals. Netflix achieved an 89% reduction in Time to First Byte (TTFB) and slashed LCP from 4.8s to a blistering 0.9s. Their Time to Interactive (TTI) also dropped from 6.2s to 1.1s, while CLS was nearly eliminated, falling from 0.34 to 0.02. By deploying to over 200 edge locations, Netflix maintains a global average response time of 67ms.  

Hulu followed a similar trajectory, incrementally migrating its "Account" application from a legacy stack to Next.js starting in 2018. A primary requirement for Hulu was Server-Side Rendering (SSR) to manage complex data dependencies while ensuring maximum SEO visibility.

By leveraging the built-in CSS-in-JS solution, Hulu implemented automatic code-splitting of styles, ensuring users only downloaded the CSS required for the specific page viewed. This kept page sizes small and improved LCP.

Swiggy and Zomato

The food-tech sector in India, dominated by Swiggy and Zomato, presents a unique challenge for rendering: millions of users on varying network speeds and mid-range mobile devices. Swiggy’s "Minis" platform, which serves a wide variety of localized experiences, was originally built using React Native Web to power mobile and desktop web from a single codebase. However, the initial client-side rendering model led to content visibility times of 7.5 seconds—unacceptable for a quick-commerce platform.  

By migrating to Next.js and implementing SSR, Swiggy reduced the time to relevant content visibility from 7.5 seconds to 5.2 seconds, a 30% improvement at the 90th percentile. This improvement was facilitated by moving the heavy data-fetching logic and initial component rendering to the server, which reduced the amount of work the user's device had to perform during the critical initial load phase.  

Zomato has similarly focused on backend and frontend optimizations to manage over 1.5 lakh restaurant partners and millions of daily orders. Beyond rendering, Zomato has optimized its underlying data platform by migrating workloads to AWS Graviton-based instances, resulting in a 25% performance boost and a 30% reduction in compute costs. This vertical optimization—from the database layer to the Next.js rendering layer—is essential for supporting the real-time ingest and fast query performance required for their business metrics.

DoorDash – Incremental Migration to SSR for SEO & Performance

DoorDash, a US-based food delivery company shared a detailed engineering case study of migrating their high-traffic pages to Next.js with SSR to solve performance and SEO issues. Like many, their website originally was a single-page React app (pure CSR) which caused slow loads (especially on mobile devices) and subpar SEO. The team identified SSR as a solution to send pre-rendered content faster to both users and crawlers.

Their approach was to incrementally adopt SSR so they created a Next.js server-rendered version of the homepage and certain store pages, and used a feature-flag rollout behind a reverse proxy to direct a percentage of traffic to the new SSR pages while the rest continued hitting the old CSR version. This allowed them to test and tune without risking the entire site allowing an A/B test and quick fallback if needed.

The team measured outcomes via WebPageTest and real user monitoring. The results were very positive: migrating key pages to Next.js yielded +12% and +15% faster page load times on the homepage and store page respectively, and improved Largest Contentful Paint (LCP) by ~65%. In fact, the number of “slow” (LCP > 4s) page views dropped by 95% after the SSR rollout. These are huge wins in terms of both UX and Google’s Core Web Vitals SEO signals.

DoorDash’s post-mortem advice to other engineers highlighted the importance of:

  • Incremental adoption: You can mix old and new – for instance, running SSR pages alongside existing CSR pages – to avoid a risky full rewrite and to ship improvements faster.

  • Clear success metrics: Define what “better” means (LCP, TTFB, INP etc.) and track them to validate the SSR implementation.

  • Safe rollout & fallback: Have a plan (feature flags, proxy rules) to quickly revert to the old version if the new SSR pages have problems. In DoorDash’s case, the reverse proxy acted as a circuit breaker – if the Next.js service ever failed or became slow, traffic could be routed back to the old app.

  • Don’t SSR everything blindly: Be strategic in what you render on the server. DoorDash chose a balanced approach (only what’s needed for FCP and SEO). This kept their SSR pages efficient and their infrastructure costs in check.

Key Takeaways and Best Practices đź“‹

Engineering teams around the globe have converged on a few guiding principles for rendering strategy:

  • Decide per page or feature – Use SSR/ISR for pages where SEO or real-time data is critical, and prefer SSG for marketing or content pages that don’t change often. Don’t blanket your entire app with one strategy. Many successful apps use a mix: e.g. an e-commerce site might ISR the product page and CSR the Add To Cart button (for fresh stock info), and use RSC to stream the product listing grid (for balance of speed/freshness), and SSG the about/marketing pages.

  • Measure and monitor – Introduce rendering changes carefully and track metrics (load times, LCP, INP, crawlability). DoorDash’s example showed the value of benchmarking before/after with tools like WebPageTest and PageSpeedInsights. Data will justify your decisions and catch regressions.

  • Optimize the whole picture – SSR can speed up initial content, but you must still optimize client-side assets. Avoid “SSR + huge JS payload” anti-patterns which can still hurt interactivity. Techniques like code splitting, tree shaking, CSS-in-JS and using Next.js React Server Components (to reduce JS sent to browser) should be in your toolkit.

  • Roll out gradually when possible – Especially for large apps, consider an incremental migration to Next.js or to a new rendering mode. Feature flags, A/B tests, or phased rollouts can de-risk the deployment. For example, serve a small % of traffic an SSR version and ramp it up. Have fallbacks (e.g. a reverse proxy can route users back to the old page if the new one fails).

  • Consider caching and offloading – Remember that SSR introduces server load. Many companies deploy Next.js with edge networks or their own caching layers (CDNs, reverse proxies like Nginx/HAProxy/Cloudflare/Cloudfront) to handle the traffic. Cache what you can – for instance, use stale-while-revalidate (ISR) so that even SSR pages don’t hit the origin on every single request. DoorDash limited SSR to just the content needed for first paint and cached other API calls where possible.

  • Stay updated with Next.js improvements – The framework is evolving. New features like React Server Components, streaming SSR, and edge runtime can further improve performance. Keep an eye on these if you’re an advanced user – they can sometimes eliminate the need for workarounds and make it easier to achieve the ideal mix of speed and freshness.

Next.js’s rendering flexibility is a powerful tool – but the art is in applying the right strategy to the right problem. The experiences of Netflix, Hulu, Swiggy, DoorDash, and others show that understanding your app’s needs (SEO vs real-time data vs performance constraints) is key to choosing between SSR, SSG, ISR, or CSR. By learning from these case studies, you can better architect your Next.js applications to deliver optimal user experiences in the real world, balancing lightning-fast static content with the interactivity and dynamism users expect.

Sources: The insights and data points above are drawn from publicly shared engineering blogs and talks by these companies’ teams. Links to the original source for deeper reading on that particular detail or quote.

https://bytes.swiggy.com/how-we-optimised-page-load-metrics-on-minis-7db422dff0db#:~:text=After%20implementing%20SSR%2C%20the%20time,2%20sec%20%2890%20percentile

https://aws.amazon.com/blogs/opensource/how-zomato-boosted-performance-25-and-cut-compute-cost-30-migrating-trino-and-druid-workloads-to-aws-graviton/

https://www.nextjs.cn/case-studies/hulu

https://netflixtechblog.com/making-netflix-com-faster-f95d15f2e972

https://largeapps.dev/case-studies/advanced/

Top comments (0)