0Pricing
React Academy · Lesson

unstable_cache & React cache()

Cache expensive function results per-request or across requests with Next.js cache utilities.

unstable_cache & React cache() is a free React Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Two Cache Utilities

Next.js provides two complementary caching utilities: unstable_cache for persistent cross-request caching, and React's cache() for per-request deduplication.

React cache() — Per-Request Dedup

cache(fn) from React memoizes a function's result for the duration of a single server render pass. Two Server Components calling the same cached function get the same result without a second DB/API call.

import { cache } from 'react';

export const getUser = cache(async (id: string) => {
  return db.user.findUnique({ where: { id } });
});

// Both components call getUser(id) — only one DB query fires per request
// component A: const user = await getUser('1');
// component B: const user = await getUser('1'); // uses cached result

unstable_cache — Persistent Cache

unstable_cache(fn, keyParts, options) persists the result across requests until explicitly revalidated. Think of it as fetch({ next: { revalidate } }) but for any async function (DB queries, Redis calls, etc.).

import { unstable_cache } from 'next/cache';

const getProducts = unstable_cache(
  async () => db.products.findMany(),
  ['products-list'],      // cache key parts
  { revalidate: 60, tags: ['products'] } // options
);

// In a Server Component:
const products = await getProducts();

Cache Key Parts

The second argument to unstable_cache is an array of strings forming the cache key. Include all variables that affect the output.

const getUserPosts = unstable_cache(
  async (userId: string) => db.posts.findMany({ where: { userId } }),
  ['user-posts'],         // base key
  { tags: [`user-${userId}-posts`] } // per-user tag
);

// Call with userId — Next.js appends the argument to the key:
const posts = await getUserPosts(userId);

Tags for On-Demand Revalidation

Tag cached functions and invalidate them with revalidateTag() when data changes — e.g., after a mutation in a Server Action.

// Server Action
async function createProduct(data: FormData) {
  'use server';
  await db.products.create({ data: parseFormData(data) });
  revalidateTag('products'); // invalidates all cached functions tagged 'products'
  redirect('/products');
}

Time-Based Revalidation

Set revalidate: N in options to revalidate the cache after N seconds, similar to ISR for fetch calls.

const getStats = unstable_cache(
  async () => computeHeavyStats(),
  ['dashboard-stats'],
  { revalidate: 300 } // recompute at most every 5 minutes
);

Combining cache() and unstable_cache

Use cache() inside unstable_cache for functions called from multiple places in one render: dedup within request + persist across requests.

// Deduplicate the DB call within a request:
export const getRawUser = cache(async (id: string) => db.user.findUnique({ where: { id } }));

// And cache the result persistently:
export const getUser = unstable_cache(getRawUser, ['user'], { revalidate: 60, tags: ['user'] });

Limitations of unstable_cache

unstable_cache is marked unstable because the API may change before stabilization. Cached functions cannot access request-specific data like cookies or headers.

React cache() for Layout Data

Wrap layout-level data fetches with cache() so both the layout and any nested page that calls the same function share the result within one render.

// lib/data.ts
export const getCurrentUser = cache(async () => {
  const session = await getServerSession();
  return db.user.findUnique({ where: { id: session?.userId } });
});

// layout.tsx and page.tsx both call getCurrentUser() — one DB query

When to Use Each

cache(): dedup identical calls within a render (same request). unstable_cache: persist results across multiple requests until revalidated. Use fetch + next.revalidate when calling external HTTP APIs.

Quick Check

What is the key difference between React's cache() and Next.js unstable_cache?

Recap

cache(fn) deduplicates calls within one render pass — ideal for shared layout/page data. unstable_cache(fn, keys, { revalidate, tags }) persists across requests with time-based or tag-based invalidation — ideal for expensive DB queries.

Frequently asked questions

Is the “unstable_cache & React cache()” lesson free?

Yes — the full text of “unstable_cache & React cache()” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.

What will I learn in “unstable_cache & React cache()”?

Cache expensive function results per-request or across requests with Next.js cache utilities. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start React Academy?

No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “unstable_cache & React cache()” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this React Academy lesson?

Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. fetch() with Cache Options in Next.js
  2. unstable_cache & React cache()
  3. Incremental Static Regeneration (ISR)
  4. Server Actions for Data Mutations
← Back to React Academy