1. Architecture Overview: Three-Layer Data Proxy Model
In this Nuxt 4 project using WordPress as a Headless CMS, data flows through a carefully designed three-layer proxy architecture:
Browser (Vue Components)
└── useQuery / useMutation / useGqlAsyncQuery
· Client-side cache key (FNV-1a Hash)
· In-flight request deduplication
· AbortController auto-cancellation
│ POST /api/graphql
Nitro Server (Proxy Layer)
└── /server/api/graphql.post.ts
· Operation type detection (query / mutation)
· Auth forwarding (Bearer Token + Cookie)
· SHA-256 query cache + cache index management
· In-flight request pool dedup
· Auto-retry (exponential backoff)
· Cache budget control
· Set-Cookie relay from WordPress
│ POST https://wp-api/graphql
WordPress Backend (WPGraphQL)
└── Content Types, JWT Auth, Extended Queries/MutationsCore benefits: Security (API URL hidden), Cache Control (byte-level budget), Auth Isolation (JWT in server cookies only), Fault Tolerance (auto-retry + dedup).
2. Server-Side GraphQL Proxy Layer
Core file: /server/api/graphql.post.ts
2.1 Operation Type Detection
function getOperationType(query: string): 'query' | 'mutation' | 'subscription' {
const trimmed = query.trim()
if (trimmed.startsWith('{')) return 'query'
const m = trimmed.match(/^(query|mutation|subscription)\\b/i)
if (!m) return 'query'
return m[1]?.toLowerCase()
}| Operation | Cache | Dedup | Notes |
|---|---|---|---|
query (no auth) | ✅ SHA-256 cache | ✅ In-flight pool | Public data |
query (authenticated) | ❌ No cache | ❌ No dedup | Private data |
mutation | ❌ No cache | ❌ No dedup | Write ops |
2.2 SHA-256 Caching System
const cacheKey = `graphql:${sha256(`${operationName}|${query}|${stableStringify(variables)}`)}`stableStringify sorts keys alphabetically, ensuring { id: 1, name: "foo" } and { name: "foo", id: 1 } produce identical hashes.
Cache index uses LRU eviction: Max entries (500), Max bytes (32MB), Max response bytes (256KB), TTL (120s).
2.3 In-Flight Request Pool Dedup
const upstreamResult = dedupeKey
? await graphqlInFlightPool.run(dedupeKey, fetchUpstream)
: await fetchUpstream()Prevents cache stampede: only one upstream request for concurrent identical queries.
2.4 Request Retry
const fetchUpstream = async () =>
await runWithRetry(
async () => { const rawResponse = await $fetch.raw(upstream, { ... }); ... },
{ retries: retryCount, baseDelayMs: retryDelayMs }
)Uses $fetch.raw to capture Set-Cookie headers from WordPress.
3. Client-Side Data Layer: useQuery
3.1 Dual-Mode Design
if (inSetup && immediate) {
// SSR Mode: useAsyncData
const asyncData = useAsyncData(key, async () => await request(vars), {
server: true, lazy: false, deep: false, dedupe: 'defer'
})
} else {
// CSR Mode: shallowRef + Promise dedup
const localData = shallowRef<TData | undefined>(undefined)
}Why shallowRef? ref recursively wraps large objects with reactive, adding significant overhead. shallowRef only tracks reference changes.
3.2 Client-Side In-Flight Dedup
if (inflight && inflightKey === k) {
return await inflight // Reuse existing Promise
}3.3 AbortController Cancellation
onScopeDispose(() => { if (aborter) aborter.abort() })3.4 FNV-1a Hash
function fnv1a(input: string) {
let hash = 0x811c9dc5
for (let i = 0; i < input.length; i++) {
hash ^= input.charCodeAt(i)
hash = (hash + ((hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24))) >>> 0
}
return hash.toString(16)
}Chosen for: minimal implementation (10 LOC), microsecond performance, manageable collisions.
4. Environment Variables
| Variable | Default | Description |
|---|---|---|
NUXT_GRAPHQL_CACHE_TTL | 120s | Query cache TTL |
NUXT_GRAPHQL_CACHE_MAX_ENTRIES | 500 | Max cache entries |
NUXT_GRAPHQL_CACHE_MAX_BYTES | 32MB | Total byte limit |
NUXT_GRAPHQL_UPSTREAM_RETRIES | 1 | Max retries |
NUXT_GRAPHQL_UPSTREAM_RETRY_DELAY_MS | 150ms | Retry base delay |
5. Performance Optimization
minify: 'esbuild'— 20-40x faster than tersercssMinify: true— CSS minificationassetsInlineLimit: 4096— inline < 4KB assets- GraphQL response cache: SHA-256 + LRU
- Static assets: ISR + CDN,
max-age=31536000 - KeepAlive component cache: whitelist routes, max 12 pages
pnpm memory:test # Unit tests
pnpm memory:profile # Memory profiling
pnpm memory:load # Load testing
pnpm memory:analyze # Log analysis6. Summary
- Server Proxy: API URL hiding + auth forwarding
- Smart Caching: SHA-256 keys + byte-budget + LRU eviction
- Dual Dedup: Server + client in-flight pools
- Memory Governance: shallowRef + KeepAlive + profiling tools
This architecture applies to any Nuxt project integrating an external GraphQL API.




