Skip to main content

proxy-cache

The proxy-cache plugin provides the capability to cache responses based on a cache key. The plugin supports both disk-based and memory-based caching options to cache for GET, POST, and HEAD requests.

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

Examples

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

Cache Data on Disk

On-disk caching strategy offers the advantages of data persistency when system restarts and having larger storage capacity compared to in-memory cache. It is suitable for applications that prioritize durability and can tolerate slightly larger cache access latency.

The following example demonstrates how you can use proxy-cache plugin on a route to cache data 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 APISIX returns 502 Bad Gateway or 504 Gateway Timeout due to unavailable upstreams, 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

In-memory caching strategy offers the advantage of low-latency access to the cached data, as retrieving data from RAM is faster than retrieving data from disk storage. It also works well for storing temporary data that does not need to be persisted long-term, allowing for efficient caching of frequently changing data.

In API7 Enterprise from version 3.10.0, the in-memory strategy also honors the upstream Vary response header. Responses are cached separately per variant computed from the headers listed in Vary, and responses with Vary: * are not cached.

The following example demonstrates how you can use proxy-cache plugin on a route to cache data 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: set to memory for in-memory setting.

cache_zone: set to the name of an in-memory cache zone.

cache_ttl: set the time to live for the in-memory cache to 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.

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",
"plugins": {
"proxy-cache": {
"no_cache": ["$arg_no_cache", "$http_no_cache"]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'

no_cache: If at least one of the values of the URL parameter no_cache and header no_cache is not empty and is not equal to 0, the response will not be cached.

Send a few requests to the route with the URL parameter no_cache value indicating cache bypass:

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

You should receive HTTP/1.1 200 OK responses for all requests and observe the following header every time:

Apisix-Cache-Status: EXPIRED

Send a few other requests to the route with the URL parameter no_cache value being zero:

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

You should receive HTTP/1.1 200 OK responses for all requests and start seeing the cache being hit:

Apisix-Cache-Status: HIT

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

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

The response should not be cached:

Apisix-Cache-Status: EXPIRED

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: If at least one of the values of the URL parameter bypass and header bypass is not empty and is not equal to 0, the response will not be retrieved from the cache.

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 for 502 and 504 Error Response Code

When the upstream services return server errors in the 500 range, proxy-cache plugin will cache the responses if and only if the returned status is 502 Bad Gateway or 504 Gateway Timeout.

The following example demonstrates the behavior of proxy-cache plugin when the upstream service returns 504 Gateway Timeout.

Create a route with the proxy-cache plugin and configure a dummy upstream service:

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": "/timeout",
"plugins": {
"proxy-cache": { }
},
"upstream": {
"type": "roundrobin",
"nodes": {
"12.34.56.78": 1
}
}
}'

Generate a few requests to the route:

seq 4 | xargs -I{} curl -I "http://127.0.0.1:9080/timeout"

You should see a response similar to the following:

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

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

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

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

However, if the upstream services returns 503 Service Temporarily Unavailable, the response will not be cached.