Guide

Caching

Optimize performance with multi-layer caching

Every composable call triggers a network request to your WordPress GraphQL API. Without caching, each page load costs ~200-500ms waiting for WordPress to respond. With caching enabled (the default), repeated requests resolve in ~1-5ms — making your site feel instant.

WPNuxt provides multiple layers of caching to achieve this. See How WPNuxt Works for where caching fits in the overall architecture.

Cache Layers

LayerScopeDurationPurpose
Server (Nitro)All usersConfigurableCache GraphQL responses server-side
Client (GraphQL)Per browserSessionDeduplicate identical queries during navigation
PayloadPer requestHydrationPrevent refetch after SSR

All layers work together automatically.

Server-Side Caching

WPNuxt caches GraphQL responses server-side using Nitro route rules.

How It Works

  1. First request fetches from WordPress (~200-500ms)
  2. Response is cached on the server
  3. Subsequent requests use cache (~1-5ms)
  4. With SWR enabled, stale content serves instantly while refreshing in background

Configuration

nuxt.config.ts
wpNuxt: {
  cache: {
    enabled: true,   // Default: true
    maxAge: 300,     // Default: 300 (5 minutes)
    swr: true        // Default: true
  }
}
OptionDefaultDescription
enabledtrueEnable/disable caching
maxAge300Cache duration in seconds
swrtrueStale-while-revalidate

Client-Side Caching

WPNuxt enables client-side GraphQL caching by default. This deduplicates identical queries during client-side navigation.

Per-Query Control

// Disable client caching for real-time data
const { data } = usePosts(undefined, { clientCache: false })

// Custom cache key for complex scenarios
const { data } = usePosts({ category: 'news' }, {
  cacheKey: `posts-news-${locale.value}`
})
OptionTypeDefaultDescription
clientCachebooleantrueEnable client-side caching
cacheKeystring-Custom cache key suffix

Payload Caching (getCachedData)

WPNuxt optimizes SSR payload handling with a smart getCachedData implementation:

  • During hydration: Uses payload data (no refetch needed)
  • Watch-triggered refetches: Uses cached data when available
  • Manual refresh: Always fetches fresh data

Custom getCachedData

Override the default behavior for specific use cases:

const { data } = usePosts(undefined, {
  getCachedData: (key, nuxtApp, ctx) => {
    // Always fetch fresh
    if (ctx.cause === 'refresh:manual') {
      return undefined
    }
    // Use cached data
    return nuxtApp.payload.data[key]
  }
})

The ctx.cause can be:

  • 'initial' - First load
  • 'refresh:manual' - Called refresh()
  • 'refresh:hook' - Triggered by Nuxt hook
  • 'watch' - Reactive dependency changed

When to Disable Caching

Development

// See changes immediately
wpNuxt: {
  cache: {
    enabled: false
  }
}

Real-Time Content

// Per-query: disable for live data
const { data } = useLiveComments(undefined, { clientCache: false })

// Global: short cache with no SWR
wpNuxt: {
  cache: {
    maxAge: 60,
    swr: false
  }
}

Authenticated Content

Authenticated requests bypass server cache automatically (via Authorization header). For user-specific data, disable client caching. See also Preview Mode for how caching interacts with draft content previews.

const { data } = useViewer(undefined, { clientCache: false })

High-Traffic Sites

wpNuxt: {
  cache: {
    maxAge: 3600,  // 1 hour
    swr: true
  }
}
Site TypemaxAgeswrclientCacheWhy
Blog / content site300–3600truetrueContent changes infrequently, SWR keeps it fresh
News / frequently updated60truetrueShort cache + SWR = fresh content without latency
Dashboard / real-time0falsefalseAlways fetch latest data
E-commerce catalog300truetrueProduct data is mostly stable

Cache Invalidation

Manual Refresh

const { data, refresh } = usePosts()

// Force fresh data
await refresh()

Reactive Invalidation

const category = ref('news')
const { data } = usePosts(
  { categoryName: category },
  { watch: [category] }
)

// Changing category triggers refetch
category.value = 'tech'

Server Cache

Server cache automatically expires based on maxAge. For immediate invalidation, you'll need to implement a webhook from WordPress or use a CDN with cache purge capabilities.

Copyright © 2026