Skip to main content

proxy-cache

The proxy-cache plugin caches HTTP responses by cache key to reduce repeated requests to upstream services. It supports disk-based and memory-based caching for GET, POST, and HEAD requests.

Responses can be conditionally cached based on request HTTP methods, response status codes, request header values, and more.

Authenticated consumers use separate effective cache keys by default. The in-memory strategy does not cache responses containing Set-Cookie unless cache_set_cookie is enabled, and it never caches responses marked private, no-store, or no-cache by the upstream.

Examples​

The examples below demonstrate how you can configure proxy-cache for different scenarios.

Cache Data on Disk​

Disk caching provides more capacity than memory caching and can preserve cached responses across gateway restarts when the cache directory uses persistent storage. It is suitable when durability is more important than the lowest possible cache-access latency.

The following example demonstrates how to use the proxy-cache plugin on a route to cache responses on disk.

When using the on-disk caching strategy, the cache TTL is determined by the Expires or Cache-Control response header. If neither header is present, or if the gateway returns 502 Bad Gateway or 504 Gateway Timeout due to an unavailable upstream, the cache TTL defaults to the value configured in the configuration files.

Create a route with the proxy-cache plugin to cache data on disk:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-cache-route",
"uri": "/anything",
"plugins": {
"proxy-cache": {
"cache_strategy": "disk"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'

Send a request to the route:

curl -i "http://127.0.0.1:9080/anything"

You should see an HTTP/1.1 200 OK response with the following header, showing the plugin is successfully enabled:

Apisix-Cache-Status: MISS

As there is no cache available before the first response, Apisix-Cache-Status: MISS is shown.

Send the same request again within the cache TTL window. You should see an HTTP/1.1 200 OK response with the following headers, showing the cache is hit:

Apisix-Cache-Status: HIT

Wait for the cache to expire after the TTL and send the same request again. You should see an HTTP/1.1 200 OK response with the following headers, showing the cache has expired:

Apisix-Cache-Status: EXPIRED

Cache Data in Memory​

Memory caching provides lower-latency access than disk caching but does not persist cached responses across gateway restarts. It is suitable for temporary responses that can be fetched again from the upstream service.

The in-memory strategy caches responses separately for each variant computed from the request headers listed in the upstream Vary response header. Responses with Vary: * are not cached. This behavior was introduced in API7 Enterprise 3.9.14 and 3.10.0, and in APISIX 3.17.0.

The following example demonstrates how to use the proxy-cache plugin on a route to cache responses in memory.

Create a route with proxy-cache and configure it to use memory-based caching:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-cache-route",
"uri": "/anything",
"plugins": {
"proxy-cache": {
"cache_strategy": "memory",
"cache_zone": "memory_cache",
"cache_ttl": 10
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'

❶ cache_strategy: uses the in-memory caching strategy.

❷ cache_zone: selects a configured in-memory cache zone.

❸ cache_ttl: keeps each cached response for 10 seconds.

Send a request to the route:

curl -i "http://127.0.0.1:9080/anything"

You should see an HTTP/1.1 200 OK response with the following header, showing the plugin is successfully enabled:

Apisix-Cache-Status: MISS

As there is no cache available before the first response, Apisix-Cache-Status: MISS is shown.

Send the same request again within the cache TTL window. You should see an HTTP/1.1 200 OK response with the following headers, showing the cache is hit:

Apisix-Cache-Status: HIT

Remove Cache Manually​

While cached responses normally expire based on their TTL, you might need to remove cached data before it expires.

The following example demonstrates how you can use the PURGE method to remove data cached on disk. PURGE also supports in-memory caching; to test it, use the memory cache configuration from the previous example.

Send the PURGE request to the same route URI as the cached request. The plugin derives the cache key for a PURGE request in the same way as for a request that populates the cache. Use the same host, URI, query parameters, and any other values referenced by cache_key. If the cache key is isolated by consumer, send the request as the same consumer.

PURGE removes every in-memory Vary variant indexed under the effective base cache key. This behavior was introduced in API7 Enterprise 3.9.14 and 3.10.0, and in APISIX 3.17.0.

Create a route that caches responses on disk:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-cache-route",
"uri": "/anything",
"plugins": {
"proxy-cache": {
"cache_strategy": "disk"
}
},
"upstream": {
"type": "roundrobin",
"pass_host": "node",
"scheme": "https",
"nodes": {
"httpbingo.org:443": 1
}
}
}'

Send a request to populate the cache:

curl -i "http://127.0.0.1:9080/anything"

Send the same request again and verify that the response contains Apisix-Cache-Status: HIT.

Send a PURGE request to the same URI:

curl -i "http://127.0.0.1:9080/anything" -X PURGE

You should see an HTTP/1.1 200 OK response, showing that the cached response was removed. If no cached response matches the cache key, the plugin returns HTTP/1.1 404 Not Found.

Send a GET request to the route again:

curl -i "http://127.0.0.1:9080/anything"

You should see the following header, showing that the previous cached response is no longer available:

Apisix-Cache-Status: MISS

Cache Responses Conditionally​

The following example demonstrates how you can configure the proxy-cache plugin to conditionally cache responses.

Create a route with the proxy-cache plugin and configure the no_cache attribute:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-cache-route",
"uri": "/anything/no-cache",
"plugins": {
"proxy-cache": {
"no_cache": ["$arg_no_cache", "$http_no_cache"]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'

❶ no_cache: concatenates the no_cache query parameter and request header. If the combined value is neither empty nor exactly 0, the response is not stored.

Send the following request more than once. The query parameter prevents each upstream response from being stored:

curl -i "http://127.0.0.1:9080/anything/no-cache?no_cache=1"

Each response should return HTTP/1.1 200 OK with the following header:

Apisix-Cache-Status: MISS

Now send the following request more than once. A value of 0 allows the response to be stored:

curl -i "http://127.0.0.1:9080/anything/no-cache?no_cache=0"

The first response should be a cache miss. Subsequent responses should contain:

Apisix-Cache-Status: HIT

The same condition can be supplied in a request header. Send the following request more than once:

curl -i "http://127.0.0.1:9080/anything/no-cache" -H "no_cache: 1"

Each response should remain a cache miss:

Apisix-Cache-Status: MISS

Retrieve Responses from Cache Conditionally​

The following example demonstrates how you can configure the proxy-cache plugin to conditionally retrieve responses from cache.

Create a route with the proxy-cache plugin and configure the cache_bypass attribute:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-cache-route",
"uri": "/anything",
"plugins": {
"proxy-cache": {
"cache_bypass": ["$arg_bypass", "$http_bypass"]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'

❶ cache_bypass: concatenates the bypass query parameter and request header. If the combined value is neither empty nor exactly 0, cache retrieval is skipped.

Send a request to the route with the URL parameter bypass value indicating cache bypass:

curl -i "http://127.0.0.1:9080/anything?bypass=1"

You should see an HTTP/1.1 200 OK response with the following header:

Apisix-Cache-Status: BYPASS

Send another request to the route with the URL parameter bypass value being zero:

curl -i "http://127.0.0.1:9080/anything?bypass=0"

You should see an HTTP/1.1 200 OK response with the following header:

Apisix-Cache-Status: MISS

You can also specify the value in the bypass header as such:

curl -i "http://127.0.0.1:9080/anything" -H "bypass: 1"

The cache should be bypassed:

Apisix-Cache-Status: BYPASS

Cache Gateway-Generated 502 and 504 Responses​

Disk caching stores 502 Bad Gateway and 504 Gateway Timeout responses generated when the gateway cannot reach an upstream service. Other 5xx responses are not cached by default.

The following example uses a pinned HTTPBin image with a deliberately slow endpoint. Start the example upstream using the method for your configuration workflow:

Run the example upstream on the Docker network used by the gateway. The following command uses the network created by the APISIX Docker quickstart; replace it for another Docker deployment:

docker run -d --name proxy-cache-httpbin \
--network apisix-quickstart-net \
ghcr.io/mccutchen/go-httpbin:2.25.0

Create a route that rewrites the upstream request to /delay/3 and stops waiting after one second:

curl "http://127.0.0.1:9180/apisix/admin/routes/proxy-cache-timeout" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"uri": "/timeout",
"plugins": {
"proxy-rewrite": {
"uri": "/delay/3"
},
"proxy-cache": {}
},
"upstream": {
"type": "roundrobin",
"retries": 0,
"timeout": {
"connect": 1,
"send": 1,
"read": 1
},
"nodes": {
"proxy-cache-httpbin:8080": 1
}
}
}'

Send a request to the route:

curl -i "http://127.0.0.1:9080/timeout"

After approximately one second, you should see a response containing the following status and header:

HTTP/1.1 504 Gateway Time-out
Apisix-Cache-Status: MISS

Send the same request again. The gateway should return the cached error response immediately:

curl -i "http://127.0.0.1:9080/timeout"

The response should contain:

HTTP/1.1 504 Gateway Time-out
Apisix-Cache-Status: HIT

Responses with other 5xx status codes, such as 503 Service Unavailable, are not cached by default.