Docs
Caching

Disk Cache

Learn how server-side disk caching works.

Server-side disk caching helps reduce redundant computations and significantly improves response times by storing computed data for reuse. This guide explains how to use unstable_cache for disk-based caching and its integration into your application workflow.

Option 1: unstable_cache

Next.js provides with unstable_cache a powerful tool for disk-based caching. The method consists of three core arguments:

  • fetchFunction: The function used to retrieve data.
  • keyParts: An array of unique identifiers for the cache entry to prevent data conflicts.
  • options: Additional settings, such as tags, to group related cache entries and streamline cache management.

Basic Example

Here is an example of using unstable_cache to fetch and cache contact data:

import { unstable_cache } from 'next/cache';
 
async function getContacts(params: GetContactsParams): Promise<ContactDto[]> {
  return unstable_cache(
    fetchContactsFromDatabase,
    // Use keyParts to create a unique cache entry based on parameters
    [
      'organizations',
      session.user.organizationId,
      'contacts',
      params.pageIndex,
      params.pageSize,
      params.searchQuery
    ],
    {
      // Use tags to group related cache entries for easier invalidation
      tags: [`organizations:${session.user.organizationId}:contacts`]
    }
  );
}

Type-Safe access

For better maintainability (no loose strings) and type safety, you can use caching helpers to generate keys and tags dynamically. Here is how you can integrate a helper:

import { unstable_cache } from 'next/cache';
import { Caching, OrganizationCacheKey } from '@/data/caching';
 
async function getContacts(params: GetContactsParams): Promise<ContactDto[]> {
  return unstable_cache(
    fetchContactsFromDatabase,
    Caching.createOrganizationKeyParts(
      OrganizationCacheKey.Contacts,
      session.user.organizationId,
      params.pageIndex,
      params.pageSize,
      params.searchQuery
    ),
    {
      tags: [
        Caching.createOrganizationTag(
          OrganizationCacheKey.Contacts,
          session.user.organizationId
        )
      ]
    }
  );
}

Cache invalidation

After a mutation operation, such as adding a new contact, you can revalidate related cache entries by calling their associated tags:

import { revalidateTag } from 'next/cache';
 
revalidateTag(
  Caching.createOrganizationTag(
    OrganizationCacheKey.Contacts,
    session.user.organizationId
  )
);

This ensures the cache is refreshed and includes the latest changes.

Cache namespaces

In Achromatic we defined two cache namespaces, depending if it is for a user or organization.

  • OrganizationCacheKey: Contains all organization cache keys
  • UserCacheKey: Contains all user cache keys.

Note that Next.js doesn't give you any helpers for define namespaces, it's all on us to generate the correct keys.

Option 2: "use cache"

The codebase is compatible with the experimental "use cache" directive from the Next.js canary release. Once this feature becomes stable, a codemod will be provided to seamlessly migrate your codebase from unstable_cache to "use cache". Benefits of "use cache":

  • Simplifies the caching mechanism by making it more declarative.
  • Reduces boilerplate code for caching logic.
  • Enhances developer experience with clearer syntax.

Stay tuned for updates and ensure your implementation aligns with the evolving standards in Next.js.