Loading...
Loading...
By continuing to use the platform, you accept the terms of the Privacy Policy and the use of cookies.
Caching in Next.js is one of the most complex and frequently asked topics in interviews. Next.js uses four levels of caching, each operating at its own stage.
Deduplication of identical fetch requests within a single render pass. If multiple components request the same data, the request runs once.
Caches fetch request results across user requests and deployments. Works like a CDN for data.
Caches rendered HTML and RSC Payload of static routes at build time.
Caches RSC Payload of visited routes in the browser. Back navigation is instant.
React automatically memoizes fetch requests with the same URL and parameters:
// Both components call the same fetch
// The request runs only once
async function Header() {
const user = await fetch('/api/user').then(r => r.json())
return <div>{user.name}</div>
}
async function Sidebar() {
const user = await fetch('/api/user').then(r => r.json())
return <div>{user.avatar}</div>
}
This only works during a single render pass on the server. For ORM queries (Prisma, Drizzle) use React.cache:
import { cache } from 'react'
import { db } from '@/lib/db'
export const getUser = cache(async (id: string) => {
return db.user.findUnique({ where: { id } })
})
By default fetch in Next.js caches the result in the Data Cache:
// Cached indefinitely (until revalidation)
const res = await fetch('https://api.hackfrontend.com/docs')
// Revalidate after 5 minutes
const res = await fetch('https://api.hackfrontend.com/problems', {
next: { revalidate: 300 }
})
// No caching
const res = await fetch('https://api.hackfrontend.com/feed', {
cache: 'no-store'
})
Two ways to update the Data Cache:
Time-based: data is considered stale after N seconds
const res = await fetch(url, { next: { revalidate: 60 } })
Event-based: explicit invalidation via tags
// When fetching
const res = await fetch(url, { next: { tags: ['problems'] } })
// When updating data (in a Server Action)
import { revalidateTag } from 'next/cache'
revalidateTag('problems')
Static routes are cached entirely at build time. This cache includes HTML and RSC Payload.
A route is static if it:
cookies(), headers(), searchParams)A route is dynamic if it:
cookies(), headers() or searchParamscache: 'no-store'export const dynamic = 'force-dynamic'The browser caches RSC Payload of visited pages. This enables:
Linkimport Link from 'next/link'
// Next.js automatically prefetches this page
<Link href="/problems">Problems</Link>
// Prefetching can be disabled
<Link href="/problems" prefetch={false}>Problems</Link>
Interview tip:
Router Cache often causes confusion. A page may show stale data after a mutation because the client cache has not updated yet. Solution: call router.refresh() or revalidatePath() in a Server Action.
To completely disable caching for a segment:
// app/dashboard/layout.tsx
export const dynamic = 'force-dynamic'
export const revalidate = 0