
Next.js unstable_cache is a powerful tool for optimizing performance, and with the right practices, you can unlock its full potential.
By default, unstable_cache is set to false, which means pages are re-rendered on every request. To enable it, you simply need to set it to true in your Next.js project.
To ensure optimal performance, it's essential to understand how unstable_cache works. This involves considering factors such as cache expiration, cache invalidation, and cache size limits.
In a real-world example, setting unstable_cache to true can reduce page reloads by up to 70%.
For another approach, see: Next.js
APIs and Routing
The unstable_cache API in Next.js can be tricky to work with, especially when it comes to caching. It's easy to get caught up in the details, but let's take a step back and look at how it affects our routes.
The Full Route Cache is a key player here. It prevents changes from being reflected in our application, as we saw in the example where the email didn't update after clicking the edit button.
To avoid this issue, we need to understand how the unstable_cache API works and how it interacts with our routes.
Expand your knowledge: Nextjs Context for Api Example Github
The Need for APIs

APIs are essential tools for building robust and efficient applications.
They provide a layer of abstraction between different components, allowing for greater flexibility and scalability.
In some cases, high-level caching mechanisms may not be enough, and that's where low-level cache APIs come in.
For instance, Next.js already provides high-level caching mechanisms, but they may not meet all the requirements of a specific application.
APIs can be used to fill the gaps and provide more control over caching, making them a valuable addition to any development toolkit.
Router
The Router Cache is an in-memory version of the cache stored on the client, as opposed to the Full Route Cache, which gets stored on the server.
This means that the Router Cache is split by route segments, allowing common layouts to be cached even if only one component is rendered.
The layout gets cached when either of these components is rendered, so it doesn't need to be rendered again the second time because it has already been cached.
A unique perspective: Loading Indicator in Next Js App Route Change
API
The Next.js unstable_cache API is a low-level cache API that provides more control over caching behavior than the high-level caching mechanisms provided by Next.js. It's not just a matter of using the fetch API, which is already modified by Next.js to support memoization.
The unstable_cache API fits in when you need to cache data that comes from external sources, such as database clients or GraphQL clients, where the fetch API can't be used. This is a common scenario when working with external data.
The unstable_cache API can be used to wrap database call functions and explicitly memoize them, which is necessary when using external data sources. The Next.js official documentation suggests using the React cache function for this purpose, but the unstable_cache API provides a more direct way to manage caching behavior.
The unstable_cache API is an example of how Next.js provides a range of caching options to suit different use cases. By using this API, you can gain more control over how data is cached and retrieved, which can be useful in certain situations.
You can use the unstable_cache API directly on server components to manage caching behavior, but keep in mind that these methods are "unstable" and might change in the future.
Related reading: Next Js Db
Caching Issues and Solutions
Caching issues can be frustrating, but Next.js provides a utility to fix them.
The revalidatePath function is exported from the next/cache module and can be used to invalidate the cache of a specific route.
By calling the revalidatePath function, we can tell Next.js to re-render a route with updated information.
This is exactly what we did in the updated actions.js file, where we invalidated the cache of the /user route when the user information was edited.
In real-world applications, it's common for routes to show lots of information, and we might want a more granular control over cache invalidation.
The current approach invalidates the cache for the whole /user route, which might not be ideal if the user information is just a small part of it.
To fix this, we would need a more targeted approach to cache invalidation.
Discover more: Next Js Caching
Caching Strategies
You can use unstable_cache for granular control over cache invalidation by passing the tags option with a value like ['user'].
This allows you to invalidate the cache of only the API and not the entire /user route.
Using unstable_cache directly on server components can also manage caching behavior, but keep in mind that these are "unstable" and might change in the future.
You can use unstable_cache() to cache data, but using the stable cache: 'force-cache' is more reliable if you're avoiding surprises down the road.
Here's a breakdown of caching strategies in Next.js:
You can revalidate your cached data in several ways, including setting a revalidation period using the next.revalidate option in your fetch request.
This will grab the latest data after the specified time while keeping things cached the rest of the time.
Revalidating specific bits of cached data on demand is also possible by assigning tags to your cached data and then revalidating those tags whenever needed.
You can manually refresh parts of your cache on demand without waiting for the next scheduled revalidation.
For more insights, see: Next Js Build Collecting Page Data
Advanced Caching Techniques
Next.js makes it easy to keep your cached data fresh with revalidations.
You can revalidate your cached data periodically using the next.revalidate option in your fetch request. This will grab the latest data after the specified time while keeping things cached the rest of the time.
For example, you can revalidate data every hour by setting next.revalidate to 3600 seconds.
Revalidating data on demand is also possible with tags. You can assign tags to your cached data and then revalidate those tags whenever needed.
This way, you can manually refresh parts of your cache without waiting for the next scheduled revalidation.
Expand your knowledge: Next Js Build Time Analyzer
Best Practices and Testing
The revalidate intervals should be changed depending on how often the data is changed. For example, the revalidate interval for dynamic data needs to be less compared to relatively less dynamic data to stay up-to-date and fast.
To enhance performance, store data in the cache when it involves access to large databases or frequently called APIs. This helps to reduce additional database calls.
See what others are reading: Nextjs Force Dynamic
When testing caching, include network delay to have more realistic life conditions in the test. This allows you to control the caching logic to cope with the problem of delay and the best handling of data in production.
Here are some key takeaways for testing caching:
- Test caching with network delay to simulate real-world conditions.
- Control the caching logic to handle delays and data handling effectively.
Avoid Prop Drilling
Prop drilling is a common issue in web development where data is passed down through multiple components, causing performance issues.
Next.js automatically memoizes fetch requests during server rendering, so if you fetch the same data multiple times, it's smart enough to only hit the network once.
This can be particularly useful when fetching the same data across multiple components.
You can skip the prop drilling by fetching the data once at the top and passing it down to the components that need it.
Here's an interesting read: Next Js Fetch Cache
Best Practices
To get the most out of caching, follow these best practices.
The revalidate intervals should be changed depending on how often the data is changed. For example, the revalidate interval for dynamic data needs to be less compared to relatively less dynamic data to stay up-to-date and fast.
Recommended read: Next Js Revalidate
Store data in the cache when it involves access to large databases or frequently called APIs. This helps to reduce additional database calls and enhances performance.
Set the expiry time or cache time. Set this depending on how frequently the content is changed.
Testing caching should include network delay to have more realistic life conditions in the test. That way, you can control the caching logic to cope with the problem of delay and the best handling of data in production.
Here are some key considerations to keep in mind when implementing caching:
- The revalidate intervals should be changed depending on how often the data is changed.
- Store data in the cache when it involves access to large databases or frequently called APIs.
- Set the expiry time or cache time.
- Testing caching should include network delay.
The Example App
The Example App is a great way to showcase how unstable_cache works in Next.js. It displays the current time, which updates with each refresh in development mode.
In development mode, hitting refresh updates the displayed time, generating a new console log entry with each refresh. This is because Next.js recognizes and treats this route as dynamic during the development process.
However, things behave differently in production mode. After building the app with the next build command and starting it in production mode, refreshing the page consistently displays the same time.
This behavior stems from Next.js's ability to recognize and treat this route as static during the build process. This means that the page is pre-rendered at build time, and the time is not updated when the page is refreshed.
If this caught your attention, see: Nextjs Loading Page Ssr
Best Practices and Testing
To ensure optimal performance with unstable_cache, it's essential to adjust revalidate intervals based on the frequency of data changes. This will help keep your application up-to-date and fast.
For example, if your application relies on dynamic data, you should set a shorter revalidate interval to reflect the changing nature of the data.
Store data in the cache when accessing large databases or frequently called APIs to reduce additional database calls and enhance performance.
You should also set an expiry time or cache time based on how frequently the content is changed.
Take a look at this: Nextjs Performance
Testing caching should include network delay to simulate real-life conditions and help you control the caching logic.
Here are some key considerations to keep in mind when testing caching:
- Test caching with network delay to simulate real-life conditions.
- Test caching with different data frequencies to ensure optimal performance.
- Test caching with different cache times to ensure optimal performance.
Avoid embedding caching logic into business logic by calling getCachedProduct as a helper function, as this makes the code more manageable and easier to update.
Featured Images: pexels.com


