graphql-proxy-cache
Description#
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.
Attributes#
| 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. |
Static Configurations#
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.
Examples#
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')
Cache GraphQL Queries#
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>
Bypass Cache for Mutation Operations#
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
Use In-Memory Cache#
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"
}'
Purge Cached Responses#
The Plugin exposes a PURGE endpoint for cache invalidation:
PURGE /apisix/plugin/graphql-proxy-cache/:strategy/:route_id/:cache_key
Where:
:strategy—diskormemory:route_id— the ID of the route:cache_key— the value returned in theAPISIX-Cache-Keyresponse header
To 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.
Disable Plugin#
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
}
}
}'