We use cookies to enhance your experience on the site
CodeWorlds

use cache - A new era of caching in Next.js 15

In the server rooms of Metropolis Quantum 2150, where every millisecond counts, you will learn about the revolutionary caching API introduced in Next.js 15. The

use cache
directive replaces the deprecated
unstable_cache
and brings a much more intuitive way to manage the cache.

What is the use cache directive?

use cache
is a new directive (similar to
use server
or
use client
) that marks functions or entire files as cacheable. Next.js automatically manages the cache lifecycle and revalidation.

Enabling dynamicIO

To use

use cache
, you first need to enable the experimental
dynamicIO
flag:

1// next.config.js
2module.exports = {
3  experimental: {
4    dynamicIO: true,
5  },
6};

Basic use cache usage

Caching a single function

1// app/lib/data.ts
2async function getProducts() {
3  'use cache';
4
5  const response = await fetch('https://api.quantum-store.com/products');
6  return response.json();
7}

Caching an entire file

1// app/lib/cached-data.ts
2'use cache';
3
4export async function getUsers() {
5  const response = await fetch('https://api.quantum-store.com/users');
6  return response.json();
7}
8
9export async function getOrders() {
10  const response = await fetch('https://api.quantum-store.com/orders');
11  return response.json();
12}

cacheLife - Controlling cache lifetime

The

cacheLife
function lets you precisely define how long data should be stored in the cache.

Predefined profiles

Next.js ships with built-in time profiles:

1import { cacheLife } from 'next/cache';
2
3async function getNews() {
4  'use cache';
5  cacheLife('minutes'); // cache for a few minutes
6
7  return fetch('https://api.quantum-news.com/latest').then(r => r.json());
8}
9
10async function getStaticContent() {
11  'use cache';
12  cacheLife('days'); // cache for days
13
14  return fetch('https://api.quantum-cms.com/static').then(r => r.json());
15}
16
17async function getRealTimeData() {
18  'use cache';
19  cacheLife('seconds'); // cache for seconds
20
21  return fetch('https://api.quantum-sensors.com/data').then(r => r.json());
22}

Available built-in profiles:

| Profile | stale | revalidate | expire | Description | |--------|-------|------------|--------|------| |

seconds
| - | 1s | 60s | For rapidly changing data | |
minutes
| 5min | 1min | 1h | For data updated every few minutes | |
hours
| 5min | 1h | 1d | For hourly data | |
days
| 5min | 1d | 1w | For rarely changing data | |
weeks
| 5min | 1w | 30d | For near-static data | |
max
| 5min | 30d | 1y | Maximum cache duration |

Custom cacheLife configurations

You can define your own profiles in

next.config.js
:

1// next.config.js
2module.exports = {
3  experimental: {
4    dynamicIO: true,
5    cacheLife: {
6      quantumFast: {
7        stale: 10,      // seconds - time when data is "fresh"
8        revalidate: 30, // seconds - time after which to revalidate in background
9        expire: 300,    // seconds - maximum lifetime
10      },
11      quantumProducts: {
12        stale: 60,
13        revalidate: 300,
14        expire: 3600,
15      },
16    },
17  },
18};

Using a custom profile:

1import { cacheLife } from 'next/cache';
2
3async function getQuantumProducts() {
4  'use cache';
5  cacheLife('quantumProducts');
6
7  return fetch('https://api.quantum-store.com/products').then(r => r.json());
8}

Inline configuration

You can also define the configuration directly:

1import { cacheLife } from 'next/cache';
2
3async function getCriticalData() {
4  'use cache';
5  cacheLife({
6    stale: 5,
7    revalidate: 15,
8    expire: 60,
9  });
10
11  return fetch('https://api.quantum-critical.com/data').then(r => r.json());
12}

cacheTag - Tagging and selective revalidation

cacheTag
lets you label the cache with tags that can later be used for selective revalidation.

Basic tagging

1import { cacheTag, cacheLife } from 'next/cache';
2
3async function getProduct(id: string) {
4  'use cache';
5  cacheTag(`product-${id}`);
6  cacheLife('hours');
7
8  return fetch(`https://api.quantum-store.com/products/${id}`).then(r => r.json());
9}
10
11async function getCategory(slug: string) {
12  'use cache';
13  cacheTag('categories', `category-${slug}`);
14  cacheLife('days');
15
16  return fetch(`https://api.quantum-store.com/categories/${slug}`).then(r => r.json());
17}

Revalidating by tags

1// app/actions/revalidate.ts
2'use server';
3
4import { revalidateTag } from 'next/cache';
5
6export async function updateProduct(id: string, data: ProductData) {
7  // Update product in the database
8  await db.products.update(id, data);
9
10  // Revalidate cache for this product
11  revalidateTag(`product-${id}`);
12}
13
14export async function refreshAllCategories() {
15  // Revalidate all categories at once
16  revalidateTag('categories');
17}

Practical example - Quantum Store Dashboard

1// app/lib/dashboard-data.ts
2import { cacheTag, cacheLife } from 'next/cache';
3
4// Product data - cache for hours, tagged
5export async function getDashboardProducts() {
6  'use cache';
7  cacheTag('dashboard', 'products');
8  cacheLife('hours');
9
10  const response = await fetch('https://api.quantum-store.com/dashboard/products');
11  return response.json();
12}
13
14// Sales stats - cache for minutes (frequent updates)
15export async function getSalesStats() {
16  'use cache';
17  cacheTag('dashboard', 'sales');
18  cacheLife('minutes');
19
20  const response = await fetch('https://api.quantum-store.com/dashboard/sales');
21  return response.json();
22}
23
24// User data - cache for days
25export async function getUserStats() {
26  'use cache';
27  cacheTag('dashboard', 'users');
28  cacheLife('days');
29
30  const response = await fetch('https://api.quantum-store.com/dashboard/users');
31  return response.json();
32}
1// app/actions/dashboard-actions.ts
2'use server';
3
4import { revalidateTag } from 'next/cache';
5
6export async function refreshDashboard() {
7  // Revalidate the entire dashboard
8  revalidateTag('dashboard');
9}
10
11export async function refreshSalesOnly() {
12  // Revalidate only sales
13  revalidateTag('sales');
14}
1// app/dashboard/page.tsx
2import { getDashboardProducts, getSalesStats, getUserStats } from '@/lib/dashboard-data';
3import { refreshDashboard, refreshSalesOnly } from '@/actions/dashboard-actions';
4
5export default async function DashboardPage() {
6  const [products, sales, users] = await Promise.all([
7    getDashboardProducts(),
8    getSalesStats(),
9    getUserStats(),
10  ]);
11
12  return (
13    <div className="quantum-dashboard">
14      <header className="flex justify-between items-center">
15        <h1>Dashboard Quantum Store</h1>
16        <div className="flex gap-2">
17          <form action={refreshSalesOnly}>
18            <button type="submit">Refresh sales</button>
19          </form>
20          <form action={refreshDashboard}>
21            <button type="submit">Refresh all</button>
22          </form>
23        </div>
24      </header>
25
26      <div className="grid grid-cols-3 gap-6">
27        <ProductsWidget data={products} />
28        <SalesWidget data={sales} />
29        <UsersWidget data={users} />
30      </div>
31    </div>
32  );
33}

Differences between use cache and unstable_cache

| Feature | use cache | unstable_cache | |-------|-----------|----------------| | Syntax | Directive | Wrapper function | | Time configuration | cacheLife() | revalidate option | | Tagging | cacheTag() | tags option | | Scope | Function or file | Function only | | Status | Stable (Next.js 15) | Deprecated |

Migrating from unstable_cache

Before (old way):

1import { unstable_cache } from 'next/cache';
2
3const getCachedProducts = unstable_cache(
4  async () => {
5    return fetch('https://api.com/products').then(r => r.json());
6  },
7  ['products'],
8  { revalidate: 3600, tags: ['products'] }
9);

After (new way):

1import { cacheTag, cacheLife } from 'next/cache';
2
3async function getProducts() {
4  'use cache';
5  cacheTag('products');
6  cacheLife('hours');
7
8  return fetch('https://api.com/products').then(r => r.json());
9}

Summary

The

use cache
directive in Next.js 15 introduces:

  • Simpler syntax - declarative caching with a directive
  • Flexible time control -
    cacheLife
    with profiles or custom configurations
  • Selective revalidation -
    cacheTag
    for precise refresh
  • Better performance - optimized cache management

In Metropolis Quantum 2150, where data flows at the speed of light, proper caching is the difference between a lightning-fast application and one that barely keeps up. Master

use cache
and your Next.js applications will run at top speed!

Go to CodeWorlds