Data Fetching and Caching
Learn best practices for fetching data on the server or client in Next.js.
Examples
This guide will walk you through the basics of data fetching and caching in Next.js, providing practical examples and best practices.
Here's a minimal example of data fetching in Next.js:
This example demonstrates a basic server-side data fetch using the fetch
API in an asynchronous React Server Component.
Reference
fetch
- React
cache
- Next.js
unstable_cache
Examples
Fetching data on the server with the fetch
API
This component will fetch and display a list of blog posts. The response from fetch
is not cached by default.
If you are not using any Dynamic APIs anywhere else in this route, it will be prerendered during next build
to a static page. The data can then be updated using Incremental Static Regeneration.
To prevent the page from prerendering, you can add the following to your file:
However, you will commonly use functions like cookies
, headers
, or reading the incoming searchParams
from the page props, which will automatically make the page render dynamically. In this case, you do not need to explicitly use force-dynamic
.
Fetching data on the server with an ORM or database
This component will fetch and display a list of blog posts. The response from the database is not cached by default but could be with additional configuration.
If you are not using any Dynamic APIs anywhere else in this route, it will be prerendered during next build
to a static page. The data can then be updated using Incremental Static Regeneration.
To prevent the page from prerendering, you can add the following to your file:
However, you will commonly use functions like cookies
, headers
, or reading the incoming searchParams
from the page props, which will automatically make the page render dynamically. In this case, you do not need to explicitly use force-dynamic
.
Fetching data on the client
We recommend first attempting to fetch data on the server-side.
However, there are still cases where client-side data fetching makes sense. In these scenarios, you can manually call fetch
in a useEffect
(not recommended), or lean on popular React libraries in the community (such as SWR or React Query) for client fetching.
Caching data with an ORM or Database
You can use the unstable_cache
API to cache the response to allow pages to be prerendered when running next build
.
This example caches the result of the database query for 1 hour (3600 seconds). It also adds the cache tag posts
which can then be invalidated with Incremental Static Regeneration.
Reusing data across multiple functions
Next.js uses APIs like generateMetadata
and generateStaticParams
where you will need to use the same data fetched in the page
.
If you are using fetch
, requests can be memoized by adding cache: 'force-cache'
. This means you can safely call the same URL with the same options, and only one request will be made.
Good to know:
- In previous versions of Next.js, using
fetch
would have a defaultcache
value offorce-cache
. This changed in version 15, to a default ofcache: no-store
.
If you are not using fetch
, and instead using an ORM or database directly, you can wrap your data fetch with the React cache
function. This will de-duplicate and only make one query.
Revalidating cached data
Learn more about revalidating cached data with Incremental Static Regeneration.
Patterns
Parallel and sequential data fetching
When fetching data inside components, you need to be aware of two data fetching patterns: Parallel and Sequential.
- Sequential: requests in a component tree are dependent on each other. This can lead to longer loading times.
- Parallel: requests in a route are eagerly initiated and will load data at the same time. This reduces the total time it takes to load data.
Sequential data fetching
If you have nested components, and each component fetches its own data, then data fetching will happen sequentially if those data requests are not memoized.
There may be cases where you want this pattern because one fetch depends on the result of the other. For example, the Playlists
component will only start fetching data once the Artist
component has finished fetching data because Playlists
depends on the artistID
prop:
You can use loading.js
(for route segments) or React <Suspense>
(for nested components) to show an instant loading state while React streams in the result.
This will prevent the whole route from being blocked by data requests, and the user will be able to interact with the parts of the page that are ready.
Parallel Data Fetching
By default, layout and page segments are rendered in parallel. This means requests will be initiated in parallel.
However, due to the nature of async
/await
, an awaited request inside the same segment or component will block any requests below it.
To fetch data in parallel, you can eagerly initiate requests by defining them outside the components that use the data. This saves time by initiating both requests in parallel, however, the user won't see the rendered result until both promises are resolved.
In the example below, the getArtist
and getAlbums
functions are defined outside the Page
component and initiated inside the component using Promise.all
:
In addition, you can add a Suspense Boundary to break up the rendering work and show part of the result as soon as possible.
Preloading Data
Another way to prevent waterfalls is to use the preload pattern by creating an utility function that you eagerly call above blocking requests. For example, checkIsAvailable()
blocks <Item/>
from rendering, so you can call preload()
before it to eagerly initiate <Item/>
data dependencies. By the time <Item/>
is rendered, its data has already been fetched.
Note that preload
function doesn't block checkIsAvailable()
from running.
Good to know: The "preload" function can also have any name as it's a pattern, not an API.
Using React cache
and server-only
with the Preload Pattern
You can combine the cache
function, the preload
pattern, and the server-only
package to create a data fetching utility that can be used throughout your app.
With this approach, you can eagerly fetch data, cache responses, and guarantee that this data fetching only happens on the server.
The utils/get-item
exports can be used by Layouts, Pages, or other components to give them control over when an item's data is fetched.
Good to know:
- We recommend using the
server-only
package to make sure server data fetching functions are never used on the client.
Preventing sensitive data from being exposed to the client
We recommend using React's taint APIs, taintObjectReference
and taintUniqueValue
, to prevent whole object instances or sensitive values from being passed to the client.
To enable tainting in your application, set the Next.js Config experimental.taint
option to true
:
Then pass the object or value you want to taint to the experimental_taintObjectReference
or experimental_taintUniqueValue
functions: