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(), orsearchParams. - Exporting
const dynamic = 'force-dynamic'.
If none of these appear, the route is static by default and extremely fast.
Example
// 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.
// 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.
// 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.
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