Next.js has a built-in Data Cache that persists the result of data fetches across incoming server requests and deployments. This is possible because Next.js extends the native fetch API to allow each request on the server to set its own persistent caching semantics.
While both caching mechanisms help improve performance by re-using cached data, the Data Cache is persistent across incoming requests and deployments, whereas memoization only lasts the lifetime of a request.
In the browser, the cache option of fetch indicates how a request will interact with the browser's HTTP cache, in Next.js, the cache option indicates how a server-side request will interact with the server's Data Cache.
The first time a fetch request with the 'force-cache' option is called during rendering, Next.js checks the Data Cache for a cached response.
If a cached response is found, it's returned immediately and memoized.
If a cached response is not found, the request is made to the data source, the result is stored in the Data Cache, and memoized.
For uncached data (e.g. no cache option defined or using { cache: 'no-store' }), the result is always fetched from the data source, and memoized.
Whether the data is cached or uncached, the requests are always memoized to avoid making duplicate requests for the same data during a React render pass.