Dynamic vs Static Rendering

Next decides between static and dynamic rendering based on the APIs and fetch options a route uses.

Each route is rendered either statically (once, at build time, then reused) or dynamically (fresh, on every request). You usually do not choose directly — Next infers it from what your code does.

What forces dynamic rendering

  • Using cache: 'no-store' on a fetch.
  • Reading request data like cookies(), headers(), or searchParams.
  • Exporting const dynamic = 'force-dynamic'.

If none of these appear, the route is static by default and extremely fast.

Example

Example · typescript
// This route becomes dynamic because it reads cookies
import { cookies } from 'next/headers';

export default async function Page() {
  const store = await cookies();
  const theme = store.get('theme')?.value ?? 'light';
  return <p>Theme: {theme}</p>;
}

When to use it

  • A marketing landing page with no personalisation is statically rendered at build time for instant edge delivery.
  • A user account page opts into dynamic rendering because it reads cookies for the session on every request.
  • A developer adds cookies() to a route handler and notices Next.js automatically switches that route to dynamic rendering.

More examples

Force static rendering

force-static pre-renders the page at build time regardless of the fetch options used inside it.

Example · ts
// app/pricing/page.tsx
export const dynamic = 'force-static';

export default async function PricingPage() {
  const plans = await fetch('/api/plans').then(r => r.json());
  return <ul>{plans.map((p: any) => <li key={p.id}>{p.name}</li>)}</ul>;
}

Force dynamic rendering

force-dynamic ensures the page runs on the server for every request, never served from a static cache.

Example · ts
// app/dashboard/page.tsx
export const dynamic = 'force-dynamic';

export default async function DashboardPage() {
  const user = await getCurrentUser(); // reads headers/cookies
  return <p>Hello, {user.name}</p>;
}

Dynamic via cookies()

Using cookies() inside a page automatically makes Next.js render it dynamically on every request.

Example · ts
import { cookies } from 'next/headers';

export default async function Page() {
  const cookieStore = await cookies();
  const theme = cookieStore.get('theme')?.value ?? 'light';
  return <div data-theme={theme}>Content</div>;
}

Discussion

  • Be the first to comment on this lesson.