Caching Strategies For Fast Next Apps
Control route and data caching for performance under real traffic and changing content.
Four Caching Layers
Next.js caches at four levels: Request Memoization (dedupe fetch in one render), Data Cache (persistent fetch results), Full Route Cache (static page HTML/RSC payload), and Router Cache (client-side prefetched segments).
Understanding which layer serves a response explains stale behavior and guides invalidation strategy. Not all layers apply to every route — dynamic routes skip Full Route Cache.
- Request memoization per render
- Data Cache for fetch results
- Full Route Cache for static pages
- Router Cache on client
Static vs Dynamic Routes
Routes are static when using force-cache fetch defaults with no dynamic functions (cookies, headers, searchParams). Static routes pre-render at build and serve from Full Route Cache.
`export const dynamic = 'force-dynamic'` opts out of static caching entirely. `export const revalidate = 3600` enables ISR — static with timed refresh. Choose based on freshness requirements.
- Static: build-time or ISR
- force-dynamic for always fresh
- revalidate for timed refresh
export const revalidate = 3600; // ISR: refresh hourly
Cache Tags and Keys
Tag fetches with `next: { tags: ['articles'] }` and invalidate with `revalidateTag('articles')` from Server Actions or Route Handlers. Tags group related cache entries across routes.
Untagged caches rely on path-based revalidation. Tag when the same data appears on multiple routes — one invalidation updates all consumers.
- Tags group cross-route cache entries
- revalidateTag for targeted bust
- Path revalidation for route-specific cache
Opt-Out Patterns
`cache: 'no-store'` on individual fetches bypasses Data Cache. `export const fetchCache = 'default-no-store'` at route level disables fetch caching for the segment. cookies() and headers() calls implicitly dynamic rendering.
User-specific dashboards should never serve cached responses from other users — verify dynamic rendering for authenticated routes.
- no-store for always-fresh fetches
- cookies/headers trigger dynamic
- Never cache authenticated user data shared
Observability
Log cache HIT/MISS in development with Next.js debugging flags. Production monitoring should track revalidation frequency, stale response rates, and origin load after cache invalidation events.
Over-caching causes stale UX; under-caching overwhelms origin databases. Tune revalidate intervals from real content change frequency, not arbitrary defaults.
- Debug cache behavior in development
- Monitor origin load after invalidation
- Tune revalidate to content change rate