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.
This option is marked as legacy in favor of "use cache". However "use cache" is not out of canary yet. The same concept still applies, but keyParts will become implicit.
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.