Essentials

Caching

Caching Shopify Storefront API and Admin API requests, best practices and strategies for improving performance in your Nuxt Shopify app.

If you want to improve the performance of your Nuxt Shopify app, consider using a cache for your Storefront API and Admin API requests. Caching can help reduce the number of API calls, decrease latency, and improve the overall user experience.

Client side and proxy caching is only available for the Storefront API. Customer account API and Admin API requests can only be cached on the server side using Nitro's caching utilities.

Configuration

In the nuxt.config.ts, you can configure caching options for client side requests and proxied server side requests (if the proxy is enabled) in the cache property of the client configuration:

~/nuxt.config.ts
export default defineNuxtConfig({
  shopify: {
    clients: {
      storefront: {
        cache: {
          // Default cache presets for client and proxy caches
          presets: {
            short: { swr: true, maxAge: 1, staleMaxAge: 9 },
            long: { swr: true, maxAge: 3600, staleMaxAge: 82800 },
          },
        },
      },
    },
  },
})

Caching Storefront API Requests

Since the Storefront API can be used on the server and client side, there are different approaches to caching requests depending on where they are made.

Client Side and Proxy

On the client side, you can use the built-in caching mechanism provided by the useStorefront composable. The client-side cache is an in-memory LRU cache that stores the results of API requests based on the query and variables. It is set up by default and configured in the module options, but caching is opt-in per request. When making a request, you can specify caching options in the cache property of the request configuration:

The client side cache is not persistent and will be cleared when the page is refreshed.
Proxy caching is persistent and done on the server side.
~/pages/products.vue
<script setup lang="ts">
const storefront = useStorefront()

const { data } = await storefront.request(`#graphql
  query FetchProducts($first: Int) {
    products(first: $first) {
      nodes {
        ...ProductFields
      }
    }
  }
`, {
  variables: {
    first: 5,
  },

  // Set 'short' cache for client and proxy
  cache: 'short',

  // Or set client and proxy cache separately
  cache: {
    client: 'short',
    proxy: 'long',
  },
})
</script>
The proxy cache is shared by every visitor. The cache key is derived from the query, the variables and the cache tier only. Never assign a proxy cache tier to personalized queries (carts, customer data, buyer-specific pricing), or one visitor's response will be served to another. The client cache is per browser session and is not affected by this.
Known limitations:
  • In Nitro v2, stale requests may be delivered even if staleMaxAge has been reached: issue.

Server Side

On the server side, you can use Nitro's built-in caching utilities to cache Storefront API requests:

~/server/api/products.ts
export default defineCachedEventHandler(async (event) => {
  const storefront = useStorefront()

  const { data } = await storefront.request(`#graphql
    query FetchProducts($first: Int) {
      products(first: $first) {
        nodes {
          ...ProductFields
        }
      }
    }
  `, {
    variables: {
      first: 5,
    },
  })

  return data
}, {
  // Cache settings for this handler
  ttl: 1000 * 60 * 60, // 1 hour
})

Caching Admin API Requests

Since the Admin API is only accessible on the server side, you can use Nitro's caching utilities to cache Admin API requests as well:

~/server/api/orders.ts
import { z } from 'zod'

export default defineCachedEventHandler(async (event) => {
  const admin = useAdmin()

  const { id } = getValidatedQuery(event, z.object({
    id: z.string(),
  }).parse)

  const { data } = await admin.request(`#graphql
    query FetchOrder($id: ID!) {
      order(id: $id) {
        id
        name
        totalPrice
        financialStatus
        fulfillmentStatus
      }
    }
  `, {
    variables: {
      id: `gid://shopify/Order/${id}`,
    },
  })

  return data
}, {
  // Cache settings for this handler
  ttl: 1000 * 60 * 60, // 1 hour

  // Use order ID as cache key
  getKey: event => `order-${getQuery(event).id}`,
})
Copyright © 2026