Fetch API & Caching
Master the extended fetch API in Next.js — how Next.js augments the native fetch with caching, revalidation, and deduplication built in.
Last reviewed: January 2025
🔍 What Is It?
Next.js extends the native fetch API with additional options in the next namespace:
fetch(url, {
cache: 'force-cache' | 'no-store',
next: {
revalidate: number, // ISR: seconds until revalidation
tags: string[], // Tags for on-demand revalidation
}
})Caching behaviour by version:
- →Next.js 14:
fetchis cached by default (force-cache). Usecache: 'no-store'to opt out. - →Next.js 15:
fetchis NOT cached by default. Usecache: 'force-cache'ornext: { revalidate }to opt in.
Deduplication: Multiple fetch calls to the same URL within the same render pass are automatically deduplicated — the network request is made only once.
🎯 Why Do We Need It?
Without Next.js's fetch extensions, you would need to:
- →Manually implement caching with Redis or in-memory stores
- →Manually deduplicate requests (prevent the same API being called 3 times in one render)
- →Manually implement ISR-style revalidation logic
- →Manually tag cache entries for on-demand invalidation
Next.js bakes all of this into the fetch API you already know, making caching a declarative concern rather than an imperative one.
🏗️ What Happens in Real Projects?
Fetch patterns in a real CMS-driven site:
// Cached indefinitely (static)
const config = await fetch('/api/config', { cache: 'force-cache' });
// ISR: revalidate every hour
const products = await fetch('/api/products', { next: { revalidate: 3600 } });
// Always fresh (SSR)
const cart = await fetch('/api/cart', { cache: 'no-store' });
// Tagged for on-demand revalidation
const post = await fetch('/api/posts/slug', {
next: { revalidate: 3600, tags: ['posts', 'post-slug'] }
});⚙️ How It Works
Next.js fetch caching layers:
- Request deduplication — same URL + options in one render = one network request
- Data cache — persists across requests (ISR/SSG behaviour)
- Full route cache — caches the rendered HTML/RSC payload
- Router cache — client-side cache for navigation
These four caches work together. Understanding which cache you're controlling with each option is the key to avoiding stale data bugs.
💻 Example
Fetch Patterns for Every Scenario — The four fetch patterns you will use in every Next.js project.
🤔 Common Confusions
❓ Does Next.js 15 cache fetch by default?
No — this is a breaking change from Next.js 14. In Next.js 15, fetch defaults to cache: "no-store" (dynamic). In Next.js 14, fetch defaults to force-cache (static). Always set explicit cache options to make your code version-agnostic and predictable.
❓ Does the extended fetch work in Client Components?
No — the Next.js fetch extensions (caching, tags, revalidate) only work in Server Components and Route Handlers. In Client Components, fetch is the standard browser fetch with no caching extensions. Use SWR or TanStack Query for client-side data fetching with caching.
❓ Can I use axios instead of fetch in Server Components?
Yes, but you lose the Next.js caching and deduplication features. Axios is a third-party library — Next.js cannot extend it. For Server Components, use the native fetch to get all the Next.js caching benefits. For Client Components, axios is fine.
🚨 Common Production Issues
Upgrading from Next.js 14 to 15 — all your cached fetch calls become dynamic (no-store) by default, causing unexpected SSR behaviour and database load spikes. Audit all fetch calls and add explicit cache options before upgrading.
Forgetting cache: "no-store" on auth endpoints — if a fetch to /api/me is cached, all users see the same user data. Always use cache: "no-store" for any user-specific endpoint.
Deduplication only works within a single render pass — it does not persist across requests. If you need cross-request caching for DB queries, use unstable_cache or React cache().
✅ Best Practices
Always set explicit cache options — never rely on defaults (they changed between versions)
Centralise fetch functions in lib/api.ts with consistent cache options
Use tags on all ISR fetch calls to enable on-demand revalidation
Use cache: "no-store" for any endpoint that returns user-specific data
Use React cache() to deduplicate DB queries across Server Components in the same request
🏛️ Architect's Note
The Next.js fetch cache is a declarative caching system — you declare the caching intent alongside the data fetch, not in a separate caching layer. This is a significant DX improvement over manually managing Redis TTLs.
However, the changing defaults between Next.js versions are a real operational risk. Establish a team convention: always explicit, never default. Every fetch call in your codebase should have an explicit cache option, documented with a comment explaining why.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
↗ Where this topic fits
Next.js Technology Guide
Return to the Next.js learning hub.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Sources
Sources / References
Use these Next.js references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide Next.js learning path
Browse the full Next.js topic collection and learning order on SplashRide.
Next.js Interview Prep
Practice Next.js interview questions and scenario-based answers.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Next.js Server Data Fetching: Async Server Components and Caching
Learn Next.js server data fetching with async Server Components, parallel and sequential requests, direct database access, caching, loading, and error handling.
Revalidation
Master Next.js revalidation — time-based, on-demand, and tag-based strategies for keeping cached content fresh without sacrificing performance.