nextjs6 min read

Caching and Revalidation Without Cargo Culting

Understand Next.js App Router caching layers—fetch cache, full route cache, and revalidation—so product teams speed up pages deliberately instead of copying cache: 'no-store' everywhere.

Slow pages frustrate users; stale pages frustrate support. Next.js App Router caching exists to balance both, but teams often react by disabling cache entirely—cache: 'no-store' on every fetch—or by assuming defaults they never measured. That is cargo cult caching: rituals copied without understanding what is cached, for how long, and who invalidates it.

This post explains the mental model from the official caching guide, when to use revalidation, and how product requirements map to tags and paths. It pairs with Static export vs SSR: when each wins and SEO architecture for Next.js product sites for public freshness expectations.

Layers: what can be cached

App Router caching is not one switch. Roughly:

  • Request memoization — Dedupes identical fetches in a single render pass.
  • Data cache — Persists results of fetch and similar across requests when allowed.
  • Full route cache — Stores rendered route output for static paths when eligible.
  • Router cache — Client-side reuse of RSC payloads on navigation (distinct from CDN HTML cache).

Read the caching overview when onboarding—PMs need the diagram-level version; engineers need segment config details. Miscommunication here shows up as “I deployed but pricing did not change” or “dashboard shows yesterday’s usage forever.”

Fetch options and product freshness classes

fetch(url, { next: { revalidate: 3600 } }) ties data cache lifetime to seconds. Time-based revalidation suits content with known staleness tolerance: integration lists, changelog indexes, marketing stats that update hourly—not millisecond trading data.

cache: 'no-store' opts out of persistent data cache—appropriate for authenticated per-user reads and live entitlements. Do not apply it to public blog indexes by default; public content belongs in scheduled or on-demand revalidation aligned with editorial cadence.

Classify routes like inventory in operations:

  • Public marketing — Long revalidate or static build; purge on deploy.
  • Catalog — Medium revalidate; on-demand when CMS publishes.
  • Account — No store or short TTL; user-specific.

High-converting SaaS marketing sites that stay fast often win on aggressive but intentional caching of hero and pricing shells with edge CDN on top.

on-demand revalidation

When an editor publishes, waiting for TTL expiry is unacceptable. Next.js supports revalidate by path or tag via route handlers or server actions calling revalidatePath and revalidateTag.

Product workflow: CMS webhook → secured revalidation endpoint → tags attached to fetches in affected templates. Document which tags map to which templates (blog-post, pricing, integrations-list). Without a tag map, engineers revalidate / blindly and hope.

For static export deployments, on-demand revalidation applies differently—often you rebuild artifacts instead. Know your hosting model before promising instant CMS updates to marketing.

Route segment config: dynamic and static

dynamic, revalidate, and related segment exports declare route-level behavior. A parent layout marked dynamic can drag children into dynamic rendering—review nested trees when only one leaf needs cookies.

Public blog [slug] routes should remain static or time-revalidated; authenticated /settings should not inherit marketing’s long cache. Split layouts physically when boundaries blur.

Tags versus paths

Tags group data dependencies across routes—ideal when one CMS entry appears on homepage teaser and /blog/[slug]. Paths target specific URLs—ideal for “this pricing page changed.” Use both deliberately; over-tagging makes invalidation noisy, under-tagging leaves stale teasers.

Run a tabletop exercise: “Pricing changes at 9am—what revalidates, in what order, and what do we show if webhook fails?” PMs own the SLA; engineering owns the handler.

Debugging stale content

When stakeholders report stale UI, trace:

  1. Was deploy successful?
  2. Is data cache TTL still active?
  3. Did CDN edge cache ignore Cache-Control?
  4. Is client router cache showing old RSC payload on back navigation?
  5. Did fetch dedupe hide a second source still cached?

Log revalidation calls in staging; verify tags on fetches match webhook payloads. Support should know difference between “hard refresh” and “wait for TTL.”

Caching and SEO

Search engines see HTML after caches resolve. Long TTL on public articles is fine if content is stable; breaking news needs shorter revalidate or on-demand purge when titles change. Align with Metadata API patterns for SEO so metadata regeneration follows the same invalidation as body content.

Avoid serving personalized pricing to anonymous crawlers via cached SSR mistakes—cache keys must respect auth boundaries.

AI and tool-heavy routes

AI streaming routes and MCP-backed tools usually should not cache model output in shared data cache. Separate tool results with user scope from public docs cached aggressively. Building AI-powered software products in 2026 emphasizes boundaries; caching violates those boundaries when one user’s context leaks to another via a shared key.

Rate-limit and cache idempotent read tools only when product spec says so—with explicit TTL and scope in the key.

Observability

Measure cache hit rates at CDN and application layer where available. Performance budgets in the sibling shipping fast with a performance budget post assume you know p95 before and after caching changes—do not ship blind.

Anti-patterns

Global no-store — Fixes staleness, destroys TTFB and origin load.

Infinite revalidate: false on mutable CMS data — Static until manual redeploy only; surprises non-engineers.

Revalidate everything on any CMS save — Thundering herd; narrow tags.

Ignoring CDN — App cache fresh but edge serves week-old HTML.

Caching error responses — Retry logic and status-aware cache rules matter.

unstable_cache and server-only helpers

Beyond raw fetch, Next.js offers unstable_cache for wrapping non-fetch data sources—ORM queries, file reads, CMS SDK calls— with tag and revalidate options. Product teams using headless CMS or SQL should ask engineers to apply the same freshness classes as HTTP fetches, not leave database reads uncached by habit.

Name cache keys and tags after business objects (product:123, blog:slug) so webhooks from CMS map cleanly. Avoid anonymous keys that force full-site invalidation.

User sessions and cache isolation

Never share data cache entries across users for personalized responses. If a Server Component reads session cookies, ensure caching semantics respect per-user variance—often no-store for that subtree while sibling public routes remain static. Security reviews should include cache key inspection, not only auth middleware.

Support macros should explain why two browsers see different data—cache TTL versus entitlement lag—not vague “try again.”

Treat cache invalidation drills like incident practice: simulate CMS outage and webhook failure, confirm marketing can still publish via rebuild fallback, and document comms templates for “pricing may take up to N minutes to propagate.” Clarity reduces churn during launches more than pretending everything is instant.

When migrating from Pages Router to App Router, re-audit caching assumptions—defaults and APIs differ. A _app pattern that implicitly refreshed data may need explicit tags in App Router fetches; schedule migration QA with content editors watching publish flows, not only engineers watching deploy logs.

Editors should see timestamps or “last updated” on preview when TTL delays propagation—small UX honesty prevents support tickets accusing the product of lying.

Collaboration checklist

  • Freshness class per route template documented.
  • Tag/path map maintained with CMS webhooks.
  • Preview environments bypass or shorten cache to avoid confusion.
  • Runbooks for failed revalidation (fallback rebuild).

Closing

Caching in Next.js is a product policy encoded in code, not a performance Easter egg. Learn the official caching layers, classify data by staleness and sensitivity, use tags and paths for surgical invalidation, and measure before disabling cache out of fear. Teams that do this ship pages that feel fast without teaching customers to distrust what they see on screen.

Let's talk