nextjs-caching

$npx mdskill add HoangNguyen0403/agent-skills-standard/nextjs-caching

Next.js 4 distinct caching layers. Understanding them prevents stale data bugs.

SKILL.md

.github/skills/nextjs-cachingView on GitHub ↗
---
name: nextjs-caching
description: 'Configure the 4 caching layers in Next.js: request memoization, data cache, full-route cache, and router cache. Use when setting revalidation strategies, invalidating cached data with tags, or diagnosing stale data bugs.'
metadata:
  triggers:
    files:
    - '**/page.tsx'
    - '**/layout.tsx'
    - '**/action.ts'
    keywords:
    - unstable_cache
    - revalidateTag
    - Router Cache
    - Data Cache
---
# Caching Architecture

## **Priority: P1 (HIGH)**

Next.js 4 distinct caching layers. Understanding them prevents stale data bugs.

## Workflow: Configure Caching for Feature

1. **Choose cache strategy** — SSG (`force-cache`), ISR (`revalidate: N`), or SSR (`no-store`).
2. **Tag cacheable fetches** — Add `next: { tags: ['posts'] }` to fetch options.
3. **Invalidate on mutation** — Call `revalidateTag('posts')` in Server Actions.
4. **Deduplicate requests** — Wrap shared data fetches with React `cache()`.
5. **Clear client cache** — Use `router.refresh()` after client-side mutations.

## Cache Invalidation Example

See [implementation examples](references/implementation.md)

## Implementation Guidelines

- **Next.js 15+ Standard**: Use **`fetch`** with **`revalidate: number`** or **`cache: 'force-cache'`** for API calls. Use **`unstable_cache`** or new **`'use cache'`** (experimental) for custom data stores.
- **Layers**: Distinguish between **Data Cache** (persistent across requests) and **Request Memoization** (React's lifecycle specific). Use **`cache()`** from React to deduplicate fetches within single render.
- **Invalidation**: Use **`revalidatePath('/')`** after mutations or **`revalidateTag('tag-name')`** for granular cache purging.
- **Client Cache**: Understand **Router Cache** (in-memory on client) and its 30s-min lifespan. Clear it using **`router.refresh()`**.
- **Static Assets**: Leverage **`generateStaticParams`** for pre-rendering static routes at build time. Use **ISR (Incremental Static Regeneration)** for content that updates periodically.
- **Streaming**: Combine **`Suspense`** with **`fetch`** triggers to prevent slow data from blocking entire page render.
- **Next.js 16+**: Favor **`'use cache'`** and **`cacheLife()`** over `revalidate: number` where available for deterministic caching.

| Layer | Where | Control |
| :---------------------- | :----- | :----------------------------- |
| **Request Memoization** | Server | React `cache()` |
| **Data Cache** | Server | `'use cache'`, `revalidateTag` |
| **Full Route Cache** | Server | Static Prerendering |
| **Router Cache** | Client | `router.refresh()` |

## **Implementation Details**

See [Cache Components & PPR](references/CACHE_COMPONENTS.md) for detailed key generation, closure constraints, and invalidation strategies.

## Anti-Patterns

- **No `unstable_cache` in Next.js 16+**: Use `'use cache'` directive with `cacheLife()` instead.
- **No `router.refresh()` for server data**: Prefer `revalidateTag()` for targeted cache busting.
- **No caching user-specific data at route level**: Wrap personal data in `<Suspense>` with `'use cache'`.
- **No long-lived cache without tags**: Assign `cacheTag()` for fine-grained invalidation control.

More from HoangNguyen0403/agent-skills-standard

SkillDescription
android-agp-upgradeUpgrade an Android project to Android Gradle Plugin (AGP) 9. Use when migrating to AGP 9, updating Gradle build files, migrating to built-in Kotlin, or adopting the new AGP DSL.
android-architectureApply Clean Architecture layering, modularization, and Unidirectional Data Flow in Android projects. Use when setting up project structure, placing code in layers, configuring feature/core modules, or implementing UDF patterns.
android-background-workImplement WorkManager and background processing correctly on Android. Use when creating Worker classes, scheduling tasks, choosing between WorkManager and Foreground Services, or setting up Hilt in workers.
android-composeBuild high-performance declarative UI with Jetpack Compose. Use when writing Composable functions, optimizing recomposition, hoisting state, or working with LazyColumn and side effects.
android-compose-migrationMigrate an Android XML View to Jetpack Compose following a structured 10-step workflow. Use when converting XML layouts to Compose, setting up Compose in an existing View-based project, or incrementally adopting Compose.
android-concurrencyWrite correct coroutine scopes, Flow collection, and dispatcher injection in Android. Use when writing suspend functions, choosing between StateFlow and SharedFlow, or injecting Dispatchers for testability.
android-deploymentConfigure release signing, R8 obfuscation, and App Bundle publishing for Android. Use when setting up signing configs, enabling minification, adding ProGuard keep rules, or preparing for Play Store submission.
android-design-systemEnforce Material Design 3 theming and design token usage in Jetpack Compose. Use when implementing M3 components, color schemes, typography, or design tokens.
android-diConfigure Hilt dependency injection with proper scoping, modules, and constructor injection in Android. Use when setting up Hilt DI, defining modules, or configuring component scoping.
android-edge-to-edgeMigrate a Jetpack Compose app to edge-to-edge display and fix system bar inset issues. Use when UI components are obscured by navigation/status bars, fixing IME insets, or enabling edge-to-edge for SDK 35+.