In Next.js, Static Rendering and Dynamic Rendering determine when HTML is generated.
| Option | Generated When | Cached | Use Case |
|---|---|---|---|
| Default Static | Build Time | Yes | About, Contact |
dynamic = "force-static" | Build Time | Yes | Landing Pages |
next: { revalidate: 60 } | Every 60 sec | Yes | Job Listings, Blogs |
cache: "no-store" | Every Request | No | Dashboard, Admin |
dynamic = "force-dynamic" | Every Request | No | Profile, Cart, Orders |
| Feature | Static Rendering | Dynamic Rendering |
|---|---|---|
| HTML Generated | At build time | On every request |
| Speed | Very fast | Slower than static |
| Server Load | Low | Higher |
| SEO | Excellent | Excellent |
| Best For | Blog, Landing Page, Job Listings | User Dashboard, Live Data |
| Data Freshness | May become outdated | Always fresh |
In Next.js App Router, there are 4 major rendering/caching options you should know.
1. Static Rendering (Default)
Page is generated once and cached.
async function getJobs() {
const response = await fetch(
"https://api.example.com/jobs"
);
return response.json();
}
export default async function Page() {
const jobs = await getJobs();
return <h1>{jobs.length}</h1>;
}
What happens?
next build
↓
Fetch Data
↓
Generate HTML
↓
Store in cache
↓
Serve same HTML to everyone
Best For
- About Us
- Contact Us
- Service Pages
- SEO Landing Pages
2. Force Static
Even if Next.js suspects dynamic behavior, force it to be static.
export const dynamic = "force-static";
export default function Page() {
return <h1>Static Page</h1>;
}
What happens?
Build Time Rendering
Only Once
Best For
/about
/privacy-policy
/terms
3. Dynamic Rendering (SSR)
Generate page on every request.
export const dynamic = "force-dynamic";
async function getJobs() {
const response = await fetch(
"https://api.example.com/jobs",
{
cache: "no-store"
}
);
return response.json();
}
export default async function Page() {
const jobs = await getJobs();
return (
<div>
{jobs.map((job:any) => (
<p key={job.id}>{job.title}</p>
))}
</div>
);
}
What happens?
User Request
↓
Run API
↓
Generate HTML
↓
Return HTML
Every request:
Fresh Data
Fresh HTML
Best For
/dashboard
/profile
/admin
/cart
/orders
4. cache: “no-store”
Forces fresh fetch every time.
const response = await fetch(
"https://api.example.com/jobs",
{
cache: "no-store"
}
);
Equivalent behavior:
export const dynamic = "force-dynamic";
Meaning
Don't cache
Always fetch latest data
5. ISR (Incremental Static Regeneration)
Most useful feature.
const response = await fetch(
"https://api.example.com/jobs",
{
next: {
revalidate: 60
}
}
);
Meaning
Cache page
After 60 seconds
Regenerate in background
Flow
First User
↓
Generate HTML
↓
Cache
Next 60 seconds
↓
Serve Cache
After 60 seconds
↓
Generate New Version
Example Timeline
next: {
revalidate: 60
}
10:00 First User
Generate Page
10:01
Serve Cached Page
10:02
Serve Cached Page
10:03
Serve Cached Page
10:04
Serve Cached Page
10:05
60 seconds completed
Regenerate Page
Job Portal Example
Home Page
export const dynamic = "force-static";
Reason:
SEO
Fast
Rarely changes
Job Category
const response = await fetch(
"https://api.cybotrix.com/categories",
{
next: {
revalidate: 300
}
}
);
Reason:
Jobs update occasionally
Need SEO
Need speed
Job Details
const response = await fetch(
"https://api.cybotrix.com/job/react-developer",
{
next: {
revalidate: 60
}
}
);
Reason:
Job status may change
SEO required
Candidate Dashboard
export const dynamic = "force-dynamic";
or
const response = await fetch(
"/api/dashboard",
{
cache: "no-store"
}
);
Reason:
User-specific data
Always fresh
Summary Table
| Option | Generated When | Cached | Use Case |
|---|---|---|---|
| Default Static | Build Time | Yes | About, Contact |
dynamic = "force-static" | Build Time | Yes | Landing Pages |
next: { revalidate: 60 } | Every 60 sec | Yes | Job Listings, Blogs |
cache: "no-store" | Every Request | No | Dashboard, Admin |
dynamic = "force-dynamic" | Every Request | No | Profile, Cart, Orders |
Interview Answer (Short)
Static Rendering:
HTML is generated at build time and reused for all users.
Dynamic Rendering:
HTML is generated on every request and always shows fresh data.
ISR:
A hybrid approach where HTML is cached and automatically regenerated after a specified interval using revalidate.
For your recruitment portal, the usual pattern is:
Home Page → force-static
Job Categories → revalidate: 300
Job Details → revalidate: 60
Blog → revalidate: 1800
Candidate Panel → force-dynamic
Admin Panel → force-dynamic
