GraphQL

Cache GraphQL responses with Zuplo

GraphQL clients send queries as POST request bodies, so a normal CDN — which keys on the URL — can't cache them. The graphql-cache-inbound policy solves this: it parses each query, normalizes it into a canonical form, and caches the response in a ZoneCache at the edge. Two requests that are semantically identical share a cache entry even when their bodies differ byte-for-byte.

Only query operations are cached. Mutations, subscriptions, malformed documents, and responses that contain GraphQL errors are always forwarded to your origin untouched.

Add the cache policy

Add graphql-cache-inbound to the inbound policies of your GraphQL route.

  1. Open policies.json

    In the Zuplo Portal, open the Code tab and add the policy definition:

    JSONconfig/policies.json
    { "name": "graphql-cache", "policyType": "graphql-cache-inbound", "handler": { "export": "GraphQLCacheInboundPolicy", "module": "$import(@zuplo/graphql)", "options": { "cacheName": "graphql-responses", "ttlSeconds": 60 } } }
  2. Attach it to your GraphQL route

    Add "graphql-cache" to the route's inbound policies in routes.oas.json, ahead of any policy that rewrites the request.

  3. Verify the cache is working

    Send the same query twice and inspect the response headers. The policy adds x-cache: MISS on the first request and x-cache: HIT on the second. The x-cache-key header (first 8 characters of the cache key) confirms two requests resolve to the same entry.

Cache authenticated traffic safely

By default, requests that carry an authorization or cookie header are not cached — otherwise the first user's response would be served to everyone. To cache per-user, list the headers that make a response user-specific in cacheKeyHeaders. Each distinct value gets its own entry:

JSONconfig/policies.json
{ "options": { "ttlSeconds": 30, "cacheKeyHeaders": ["authorization"] } }

Setting cacheKeyHeaders to an empty array [] caches a single response and shares it across all callers. Only do this when the response genuinely doesn't depend on who is calling — otherwise one caller's data leaks to others.

See the GraphQL Cache policy reference for the full option matrix, including how credentialed requests fail safe.

Next steps

Last modified on