Next.js Curriculum
MediumCaching Architecture100% Free25 min read

Dynamic Rendering vs Static Rendering Triggers

The 30-Second Interview Answer

In Next.js App Router, routes are statically prerendered by default unless they consume dynamic functions (cookies(), headers(), searchParams) or an uncached data source. When a dynamic trigger is accessed, Next.js automatically switches that segment from static build-time generation to request-time dynamic rendering.

Learning Objectives

Identify the exact functions and APIs that trigger dynamic rendering.

Inspect build output indicators (○ Static vs λ Dynamic) to audit route rendering mode.

Use Route Segment Config options (dynamic = "error" / "force-static") to enforce static guarantees.

Isolate dynamic functions to child components to keep parent layouts static.

Prerequisites & Background Knowledge
Static Site Generation (SSG)Server-Side Rendering (SSR)Build process output

Why Interviewers Care

Essential for maintaining high CDN cache-hit rates and keeping cloud server compute costs under control.

The Challenge

List all triggers that switch a Next.js route from static to dynamic rendering. How can you programmatically prevent accidental dynamic bailout in production codebases?

Code Architecture & Implementation

1// app/marketing/page.tsx
2// 1. Force Next.js to fail the build if any dynamic function is introduced
3export const dynamic = 'error';
4
5// If someone tries to use cookies() or headers() here, the build throws:
6// "Error: Page couldn't be rendered statically because it used cookies()"
7
8export default async function StaticMarketingPage() {
9 const content = await fetch('https://api.cms.com/marketing', {
10 next: { revalidate: 86400 } // 24-hour ISR
11 }).then(res => res.json());
12
13 return (
14 <main>
15 <h1>{content.headline}</h1>
16 <p>{content.body}</p>
17 </main>
18 );
19}

Architectural Explanation

The dynamic triggers in Next.js are: 1) cookies(), 2) headers(), 3) searchParams page props, and 4) fetch(..., { cache: "no-store" }) when unconfigured. When Next.js encounters any of these during next build, it aborts static generation for that route and marks it with the λ symbol in the terminal output. By wrapping dynamic components in <Suspense>, developers allow the surrounding shell/layout to be prerendered statically while only streaming the dynamic component at request time.

Common Mistakes & Anti-Patterns

Reading `cookies()` in the root `layout.tsx`, accidentally turning the ENTIRE website dynamic.

Using `searchParams` in a page when an interactive Client Component with `useSearchParams()` inside `<Suspense>` could keep the page shell static.

Not reviewing `npm run build` output symbols (○ vs λ) before deploying to production.

Interview Follow-Up Traps

The interviewer asks: "Does calling headers() inside a generateMetadata function make the page dynamic?" Yes! `headers()` inside `generateMetadata()` triggers dynamic rendering for the entire route.

Frequently Asked Questions

What do the symbols ○, ●, and λ mean in Next.js build output?

○ represents Static (prerendered HTML), ● represents SSG with generateStaticParams, and λ represents Dynamic (server-rendered on demand).

No. `cookies()` will return empty objects or throw an error.

Under PPR, routes are no longer strictly all-or-nothing; static shells are always prerendered, and dynamic triggers are isolated to streamed Suspense holes.