NB logo
Caching in Next.js - Complete Beginner’s Survival Guide blog image

Caching in Next.js - Complete Beginner’s Survival Guide

profile

Nitesh Babu

05 November 2025

Caching can feel like one of those mysterious concepts that everyone talks about but very few truly understand. Lucky for you, Next.js makes caching far more intuitive once you know what levers to pull. This guide breaks everything down in simple, friendly language with visuals, code examples, and clear mental models.

If you want to check the official documentation at any point, look for the word reference throughout this guide. Each one links to the corresponding Next.js page.

Why Caching Matters

Caching helps your app respond faster by storing and reusing data or rendered results instead of recreating them every time. When done right, it dramatically boosts performance and reduces server load.

Here is the basic idea.
Cache Flow Diagram

  • A request comes in.
  • If the data exists in a cache, it is returned instantly.
  • If it does not, the server fetches fresh data, stores it, and returns it.

This keeps your app responsive even during heavy traffic.

The Next.js Mental Model

Next.js uses a concept called Request Memoization. If you fetch the same resource multiple times during a request, Next.js automatically reuses the result. This makes data fetching predictable and efficient.

deduplicated requests

You can read more about this in the official caching docs.

Static Caching

Static caching stores the result during the build step.

Here is a simple example.

// This fetch runs at build time
export default async function Page() {
	const response = await fetch('https://pokeapi.co/api/v2/pokemon/ditto')
	const data = await response.json()

	return <pre>{JSON.stringify(data, null, 2)}</pre>
}

Because fetch runs without any caching options, it defaults to static caching. The result will not change until you rebuild the app.

Dynamic Caching

If you need fresh data every time, use dynamic caching.

Here is the simplest way.

export default async function Page() {
	const response = await fetch('https://api.example.com/live', {
		cache: 'no-store',
	})

	const data = await response.json()

	return <p>Live Value {data.value}</p>
}

The no-store option forces Next.js to fetch the data on every request. Great for stock prices, analytics, or authenticated user data.

Revalidating Data

Sometimes you want data to be cached, but refreshed periodically. This is where revalidation shines.

export default async function Page() {
	const response = await fetch('https://api.example.com/blog', {
		next: {
			revalidate: 60,
		},
	})

	const posts = await response.json()

	return (
		<section>
			{posts.map((post) => (
				<p key={post.id}>{post.title}</p>
			))}
		</section>
	)
}

Next.js will serve cached data instantly. Every 60 seconds it refreshes the cache in the background. This is known as Incremental Static Regeneration.

Route Segment Caching

The App Router introduced a superpower called Partial Rendering. Each layout, page, and loading state has its own cache boundary.

For example.

// layout.js
export const revalidate = 120

export default function Layout({ children }) {
	return <div>{children}</div>
}

This means everything inside this layout benefits from two minutes of caching.

Manual Cache Control with unstable_cache

When you need custom caching behavior, unstable_cache gives you manual control.

// layout.js
import { unstable_cache } from 'next/cache'

async function getArticles() {
	const response = await fetch('https://api.example.com/articles')
	return response.json()
}

export const cachedArticles = unstable_cache(getArticles, ['articles-key'], {
	revalidate: 300,
})

You decide the key, the duration, and what gets stored. This is useful for expensive queries or shared API calls.

CDN Level Caching

If you deploy on Netlify, their Edge Network automatically caches static responses globally. This is why static sites load extremely fast in any geography.

Common Mistakes Beginners Make

  • Using no-store everywhere breaks performance
  • Putting revalidate on both layout and page leads to confusion
  • Fetching inside client components ruins caching
  • Fetching identical data in multiple places without using the same key wastes requests
  • Not understanding that cookies and headers can make caches dynamic

Caching in Next.js feels complicated until you see the big picture.Once you learn the differences between static, dynamic, and revalidated caching, everything begins to click. The framework handles a huge amount of the complexity for you, leaving you to focus on real product features.


🔗 Share this post

Spread the word wherever you hang out online.

Related Posts

Be part of the thinking behind the craft.

Why real systems behave the way they do. Technical paths that change outcomes.
The web’s native language, decoded.

Monthly. No pandering, no gimmicks, no shallow summaries.