title: graphql-proxy-cache keywords:
The graphql-proxy-cache Plugin provides caching for GraphQL query responses. It supports both disk-based and memory-based caching strategies for GET and POST requests.
The cache key is derived from the plugin configuration version, route/service/host identifiers, and the GraphQL query body:
key = md5(conf_version + host + route_id + service_id + identity + body)
Requests containing mutation operations are never cached — they always bypass the cache and reach the upstream directly.
The Plugin reuses the caching infrastructure of the proxy-cache Plugin. Cache zones must be configured in config.yaml before enabling this Plugin.
| Name | Type | Required | Default | Valid values | Description |
|---|---|---|---|---|---|
| cache_strategy | string | False | disk | [“disk”, “memory”] | Caching strategy. Use disk to cache responses on disk (via NGINX's native proxy_cache), or memory to cache in a shared memory dictionary. |
| cache_zone | string | False | disk_cache_one | Cache zone to use. The value must match one of the zones defined in the static configurations. Use a disk zone with the disk strategy and a memory zone with the memory strategy. | |
| cache_ttl | integer | False | 300 | >= 1 | Cache time to live (TTL) in seconds for the memory strategy. For the disk strategy, TTL is controlled by the upstream Expires or Cache-Control response headers; if neither is present, the cache_ttl configured in config.yaml is used. |
| consumer_isolation | boolean | False | true | If true, partition the cache by authenticated identity. When the request resolves to an APISIX consumer (ctx.consumer_name) or carries a remote user (ctx.var.remote_user), the identity is prepended to the effective cache key so each consumer gets its own cache namespace. Set to false if you want different consumers to share cached responses. | |
| cache_set_cookie | boolean | False | false | If true, cache responses that include a Set-Cookie header. Only valid for the memory strategy — the disk strategy never caches responses with Set-Cookie (NGINX enforces this). Enable only when the upstream's Set-Cookie is not user-specific. |
The graphql-proxy-cache Plugin reuses the proxy_cache zones defined in config.yaml. Configure at least one cache zone before enabling this Plugin:
apisix: proxy_cache: cache_ttl: 10s # default TTL for disk cache when Expires/Cache-Control are absent zones: - name: disk_cache_one memory_size: 50m disk_size: 1G disk_path: /tmp/disk_cache_one cache_levels: 1:2 - name: memory_cache memory_size: 50m
Reload APISIX for changes to take effect.
The examples below demonstrate how you can configure graphql-proxy-cache for different scenarios.
:::note
You can fetch the admin_key from config.yaml and save it to an environment variable with the following command:
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
:::
The following example shows how to enable graphql-proxy-cache on a route with the default disk strategy:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "plugins": { "graphql-proxy-cache": {} }, "upstream": { "nodes": { "127.0.0.1:8080": 1 }, "type": "roundrobin" }, "uri": "/graphql" }'
Send a GraphQL POST request:
curl http://127.0.0.1:9080/graphql \ -H "Content-Type: application/json" \ -d '{"query": "query { persons { name } }"}'
The first request results in a cache miss:
HTTP/1.1 200 OK Apisix-Cache-Status: MISS APISIX-Cache-Key: <cache-key>
Sending the same request again returns a cache hit:
HTTP/1.1 200 OK Apisix-Cache-Status: HIT APISIX-Cache-Key: <cache-key>
graphql-proxy-cache automatically bypasses the cache for GraphQL requests containing mutation operations:
curl http://127.0.0.1:9080/graphql \ -H "Content-Type: application/json" \ -d '{"query": "mutation { addPerson(name: \"Alice\") { id } }"}'
The response includes Apisix-Cache-Status: BYPASS, and the request is forwarded directly to the upstream:
HTTP/1.1 200 OK Apisix-Cache-Status: BYPASS
The following example enables the memory strategy with a 60-second TTL:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "plugins": { "graphql-proxy-cache": { "cache_strategy": "memory", "cache_zone": "memory_cache", "cache_ttl": 60 } }, "upstream": { "nodes": { "127.0.0.1:8080": 1 }, "type": "roundrobin" }, "uri": "/graphql" }'
The Plugin exposes a PURGE endpoint for cache invalidation:
PURGE /apisix/plugin/graphql-proxy-cache/:strategy/:route_id/:cache_key
Where:
:strategy — disk or memory:route_id — the ID of the route:cache_key — the value returned in the APISIX-Cache-Key response headerTo expose the purge endpoint, create a route using the public-api Plugin:
curl http://127.0.0.1:9180/apisix/admin/routes/graphql-cache-purge \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "plugins": { "public-api": {} }, "uri": "/apisix/plugin/graphql-proxy-cache/*" }'
Then send a purge request using the cache key from a previous response:
curl http://127.0.0.1:9080/apisix/plugin/graphql-proxy-cache/disk/1/<cache-key> \ -X PURGE
A successful purge returns HTTP 200. If the cache entry does not exist, HTTP 404 is returned.
To disable the graphql-proxy-cache Plugin, remove it from the route configuration:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "uri": "/graphql", "plugins": {}, "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:8080": 1 } } }'