The biggest behavioral change in v15
In Next.js 14, fetch() in Server Components was cached by default. Developers were burned by stale data they didn't know they had. Next.js 15+ flipped the default: fetch is uncached unless you opt in.
Opt-in caching options
| Strategy | How to set it |
|---|---|
| Cache forever (until revalidate) | fetch(url, { cache: 'force-cache' }) |
| ISR — revalidate every N seconds | fetch(url, { next: { revalidate: 60 } }) |
| Tag for on-demand invalidation | fetch(url, { next: { tags: ['posts'] } }) |
| No cache (default) | fetch(url) or explicit { cache: 'no-store' } |
| Route-level default | export const revalidate = 60 |
What the migration looks like
If your v14 app feels slow after upgrading, find the routes that don't actually need fresh data on every render and add cache: 'force-cache' or next: { revalidate }. Those were getting free caching before; they aren't now.