Static vs Dynamic Rendering
How Next.js Decides When to Render
Next.js automatically decides at build time whether a route should be rendered statically (once, at build) or dynamically (on every request). You rarely need to configure this explicitly — the framework infers it from what your route does.
Static Rendering (the default)
A route is statically rendered when it has no dynamic dependencies: no cookies(), no headers(), no searchParams, and all fetch calls are cached. The HTML is generated once at build time and served from a CDN on every request.
Dynamic Rendering
A route becomes dynamically rendered the moment it calls cookies(), headers(), reads searchParams, or uses cache: "no-store". The HTML is then generated fresh on every incoming request.
import { cookies } from "next/headers";
// This page is DYNAMIC — it reads cookies at request time
export default async function ProfilePage() {
const cookieStore = await cookies();
const userId = cookieStore.get("userId")?.value;
if (!userId) return <p>Not logged in.</p>;
const user = await fetchUser(userId);
return <h1>Hello, {user.name}</h1>;
}
async function fetchUser(id: string) {
const res = await fetch(`https://api.example.com/users/${id}`, {
cache: "no-store",
});
return res.json();
}generateStaticParams for Dynamic Routes
For dynamic routes (e.g. /blog/[slug]), export generateStaticParams to pre-render a known list of slugs at build time. Any slug not in the list is rendered dynamically on demand.
// src/app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await fetch("https://api.example.com/posts").then((r) =>
r.json()
);
return posts.map((post: { slug: string }) => ({ slug: post.slug }));
}
export default async function PostPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = await fetchPostBySlug(slug);
return <article><h1>{post.title}</h1></article>;
}
async function fetchPostBySlug(slug: string) {
const res = await fetch(`https://api.example.com/posts/${slug}`);
return res.json();
}Prefer static rendering wherever possible — it is faster and cheaper. Only opt into dynamic rendering when you genuinely need per-request data (authentication, personalisation, live prices).