> This page is for Developer.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.bigcommerce.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.bigcommerce.com/_mcp/server.

# Caching

> How Catalyst uses Next.js request memoization and the Data Cache to reduce redundant GraphQL requests and lower rendering costs.

Catalyst uses several caching mechanisms in Next.js, including request memoization and the Data Cache. They improve performance, reduce redundant requests, and lower rendering costs. For background, see the Next.js [caching guide](https://nextjs.org/docs/app/guides/caching-without-cache-components).

## Request memoization

Catalyst utilizes Next.js’s [request memoization](https://nextjs.org/docs/app/guides/caching-without-cache-components#deduplicating-requests) to ensure data is fetched once during the React render cycle, even if requested multiple times within the component tree. This reduces unnecessary network requests, improving performance across your storefront.

When the same data may be fetched more than once during a single page request, Catalyst wraps the async function with React's `cache` utility. This memoizes the result and returns the cached value on subsequent calls, as in this product fetcher:

```ts {2,10} showLineNumbers={false}
export const getProduct =
  cache(
    async (entityId: number, customerAccessToken?: string) => {
      const { data } = await client.fetch({
        ...
      });

      return data.site.product;
    }
  );
```

## Data Cache

Next.js extends the native `fetch` API to cache data across requests, allowing cached data reuse until it's invalidated. This ensures faster response times and reduces the load on external APIs, like the BigCommerce GraphQL Storefront API.

Data Cache behavior is controlled by the `fetchOptions` parameter passed to the [Catalyst client](/developer/docs/storefront/catalyst/reference/client), which your project installs as the `@bigcommerce/catalyst-client` npm package. This request caches the product query using the default revalidation target:

```ts {5} showLineNumbers={false}
import { revalidate } from '~/client/revalidate-target';

const { data } = await client.fetch({
  document: ProductQuery,
  fetchOptions: { next: { revalidate } },
});
```

`fetchOptions` parameters are passed directly to `fetch` and follow the standard Next.js conventions. See the Next.js docs on the [cache](https://nextjs.org/docs/app/api-reference/functions/fetch#optionscache) and [next.revalidate](https://nextjs.org/docs/app/api-reference/functions/fetch#optionsnextrevalidate) parameters.

### Anonymous vs. customer-specific requests

By default, Catalyst uses the Data Cache for `fetch` requests for anonymous data, which account for most requests on a typical storefront.

This setup ensures non-unique, repeatable requests benefit from caching while requests affected by customer context are appropriately dynamic.

* **Cacheable data:** For data that is cacheable, such as product data, `fetchOptions` is configured to allow caching for guests and disallow it for logged-in customers.
* **Non-cacheable data:** For data that is never appropriate to cache, such as cart data, `fetchOptions` is always configured to disallow caching.

This configuration is passed on a per-request basis, so you can configure caching behavior to best suit the needs of a particular fetch.

### Cache your own requests

When you write your own API requests, use `fetchOptions` to cache anonymous data and skip the cache for customer-specific data.

This catalog fetch caches the response for guests and skips the cache for signed-in customers:

```ts showLineNumbers={false}
import { getSessionCustomerAccessToken } from '~/auth';
import { revalidate } from '~/client/revalidate-target';

const customerAccessToken = await getSessionCustomerAccessToken();

const { data } = await client.fetch({
  document: ProductQuery,
  customerAccessToken,
  fetchOptions: customerAccessToken ? { cache: 'no-store' } : { next: { revalidate } },
});
```

This cart fetch never caches the response:

```ts showLineNumbers={false}
import { getSessionCustomerAccessToken } from '~/auth';

const customerAccessToken = await getSessionCustomerAccessToken();

const { data } = await client.fetch({
  document: CartQuery,
  customerAccessToken,
  fetchOptions: {
    cache: 'no-store',
  },
});
```

### Set the cache duration

Data that isn't customer-specific is cached for 1 hour by default, set by the `revalidate` property on each `fetch`. Most functions use the [`DEFAULT_REVALIDATE_TARGET`](/developer/docs/storefront/catalyst/reference/environment-variables#default_revalidate_target) environment variable. Adjust it to suit your store's traffic and update frequency:

| Traffic | Product and category updates | Recommended value |
| ------- | ---------------------------- | ----------------- |
| High    | High                         | 1-8 hours         |
| High    | Low                          | 8-24 hours        |
| Low     | High                         | 1-8 hours         |
| Low     | Low                          | 24-48 hours       |

> **Warning**
>
> The lower the `DEFAULT_REVALIDATE_TARGET`, the more requests your store will make to the BigCommerce API, leading to rate limiting and increased costs. Monitor API usage and adjust the `DEFAULT_REVALIDATE_TARGET` accordingly.

### Rate limiting

BigCommerce GraphQL mutations are rate-limited by the request IP. Catalyst adds the shopper’s IP address to the request headers when a `fetch` request has a `cache` value of `no-store` or `no-cache`. This keeps one shopper's requests from counting against another's rate limit during high traffic.