HTTP Caching Policy | MuleSoft Documentation
# HTTP Caching Policy
**Policy Name** | HTTP caching  
---|---  
Caches HTTP responses from an API implementation  
Quality of Service  
**First Flex Gateway version available**  
**Returned Status Codes** | No return codes exist for this policy  
## Summary
The HTTP Caching policy enables you to cache HTTP responses for reuse. Caching these responses speeds up the response time for user requests and reduces the load on the backend. For example, if your backend exposes an endpoint for which the responses to requests are not likely to change, you can reuse the HTTP responses and bypass the backend request processing by using the HTTP Caching policy.
Policies applied after the HTTP Caching policy in the policy order are not applied to responses served from the cache. For example, a rate limiting policy applied after the HTTP Caching policy only limits the responses served by the upstream service but not the responses served by the cache. Apply all policies needed for the cached response before the HTTP Caching policy.
The HTTP Caching policy does not support MCP and A2A server instances.   
---  
## Configuring Policy Parameters
### Flex Gateway Local Mode
In Local Mode, you apply the policy to your API via declarative configuration files. Refer to the following policy definition and table of parameters:
```
- policyRef:
  name: http-caching-flex
 config:
  httpCachingKey: <string> // REQUIRED, default: "#[attributes.requestPath]"
  maxCacheEntries: <int> // REQUIRED, default: 10000
  ttl: <int> // REQUIRED, default: 600
  useHttpCacheHeaders: <bool> // REQUIRED, default: true
  invalidationHeader: <string> // OPTIONAL, default: ""
  requestExpression: <string> // OPTIONAL, default: "#[attributes.method == 'GET' or attributes.method == 'HEAD']"
  responseExpression: <string> // OPTIONAL, default: "#[[200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501] contains attributes.statusCode]"
  distributed: <bool> // REQUIRED, default: false
  persistCache: <bool> // REQUIRED, default: false
```

Parameter | Required or Optional | Default Value | Description  
---|---|---|---  
`httpCachingKey` |  `#[attributes.requestPath]` |  A DataWeave expression  
`maxCacheEntries` |  Specifies the maximum number of entries that can be stored in the cache at any given time  
Specifies the amount of time (in seconds) after which a single entry expires from the cache  
`useHttpCacheHeaders` |  Enables the use of Cache-Control header directives  
`invalidationHeader` |  Empty string |  A string specifying the header used to invalidate a single entry or the entire cache  
`requestExpression` |  `#[attributes.method == 'GET' or attributes.method == 'HEAD']` |  The DataWeave expression that is used to decide which requests are to be cached (caches the response only if the condition is true)  
`responseExpression` |  `#[[200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501] contains attributes.statusCode]` |  The DataWeave expression that is used to decide which responses are to be cached (caches the response only if the condition is true)  
Configures the cache to be distributed among different nodes in a cluster  
`persistCache` |  Configures the cache to persist between different restarts of the replica  
Leaving a required value blank configures the parameter as the default value. No value is configured for optional values left blank.   
---  
#### Resource Configuration Example
```
- policyRef:
  name: http-caching-flex
 config:
  httpCachingKey: "#[attributes.requestPath]"
  maxCacheEntries: 10000
  ttl: 500
  useHttpCacheHeaders: false
  requestExpression: "#[attributes.method == 'GET' or attributes.method == 'HEAD']"
  responseExpression: "#[[200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501] contains attributes.statusCode]"
```

#### Distributed Caching Resource Configuration Example
Distributed Caching requires Shared Storage to be enabled. For more information about Shared Storage, refer to Configuring Shared Storage for Flex Gateway in Connected Mode.
```
---
apiVersion: gateway.mulesoft.com/v1alpha1
kind: Configuration
metadata:
 name: shared-storage-redis
spec:
 sharedStorage:
  redis:
   address: redis:6379
   user: user
   password: pass
   DB: 1
---
apiVersion: gateway.mulesoft.com/v1alpha1
kind: PolicyBinding
metadata:
 name: ingress-http-caching
spec:
 targetRef:
  kind: ApiInstance
  name: ingress-http
 policyRef:
  kind: Extension
  name: http-caching-flex
 config:
  httpCachingKey: "#[attributes.method ++ attributes.requestPath]"
  useHttpCacheHeaders: true
  maxCacheEntries: 100
  ttl: 600
  distributed: true
  persistCache: true
  invalidationHeader: AGW-CACHE-CONTROL
```

### Managed Flex Gateway and Flex Gateway Connected Mode
When you apply the policy to your API instance from the UI, the following parameters are displayed:
**Parameter** | **Description** | **Required?**  
---|---|---  
HTTP Caching Key | A DataWeave expression. Default value: `#[attributes.requestPath]`  
Maximum Cache Entries | Specifies the maximum number of entries that can be stored in the cache at any given time. Default value: `10000`  
Entry Time To Live | Specifies the amount of time (in seconds) after which a single entry expires from the cache. Default value: `600`  
Distributed | Configures the cache to be distributed among different nodes in a cluster. Default value: `false`  
Persistent Cache | Configures the cache to persist between different restarts of the Flex Gateway instance. Default value: `false`  
Follow HTTP Caching directives | Enables the use of Cache-Control header directives. Default value: `true`  
Invalidation Header | Name of the header used to invalidate a single entry or the entire cache.  
Conditional Request Caching Expression | The DataWeave expression that is used to decide which requests are to be cached (caches the response only if the condition is true). Default value: `#[attributes.method == 'GET' or attributes.method == 'HEAD']`  
Conditional Response Caching Expression | The DataWeave expression that is used to decide which responses are to be cached (caches the response only if the condition is true). Default value: `#[[200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501] contains attributes.statusCode]`  
## How This Policy Works
When an HTTP request reaches an endpoint, what happens next depends on whether that request does not already exist in cache (a cache miss) or whether it does (a cache hit).
### Cache Miss
In a cache miss scenario, the HTTP Caching policy checks whether a response to the submitted request is already cached. The request reaches the backend and the process is initiated only when it’s a cache miss. The diagram illustrates the flow of events that occur in this scenario:
  1. The client (user) sends a request to the API.
  2. The request proceeds through other policies in the policy chain before reaching the HTTP Caching policy.
  3. The HTTP Caching policy checks if the request is already in the object store and, if not, the cache miss process is initiated.
  4. The request continues throughout the chain of other remaining policies.
  5. The request reaches the backend and completes all required processing.
  6. The backend responds and the response travels back through the policy chain.
  7. The response reaches the HTTP Caching policy.
  8. Caching hits the object store again and attempts to save the key of the request for later reuse.
  9. The response continues through the remaining policies in the policy chain.
  10. The response is returned to the client.


### Cache Hit
In a cache hit scenario, the HTTP Caching policy searches for the key in the object store and finds that the response to a request is already cached as a stored entry. The request does not proceed any further in the policy chain toward the backend, and the cached response is reused.
Subsequently, all the policies that must be executed in the policy chain after caching are not executed, in case of a cache hit:
  1. The client (user) sends a request to the API.
  2. The request crosses other policies before reaching the HTTP Caching policy.
  3. The HTTP Caching policy verifies that the request is already in the cache.
  4. The key is found in the object store and the stored response is returned.
  5. The response continues through the rest of the policy chain until it reaches the last one.
  6. The cached response is returned to the client.
### Cache Hit
In a cache hit scenario, the HTTP Caching policy searches for the key in the object store and finds that the response to a request is already cached as a stored entry. The request does not proceed any further in the policy chain toward the backend, and the cached response is reused.
Subsequently, all the policies that must be executed in the policy chain after caching are not executed, in case of a cache hit:
  1. The client (user) sends a request to the API.
  2. The request crosses other policies before reaching the HTTP Caching policy.
  3. The HTTP Caching policy verifies that the request is already in the cache.
  4. The key is found in the object store and the stored response is returned.
  5. The response continues through the rest of the policy chain until it reaches the last one.
  6. The cached response is returned to the client.


### Stored Entries
_Stored entries_ are the cached HTTP responses. The cache can store any serializable data or input streams of up to 1 MB. If that value is surpassed, then the reading stops and the value is not stored in such a case.
### HTTP Caching Key
The cache works as a dictionary, where each response stored in the cache is associated with a string called _key_. For example, the expression #[attributes.headers['key']] uses the header called `key` as the entry key. You can use any DataWeave expression that returns a string, including predefined DataWeave variables.
### Cache Size and Entry Expiration
The cache can hold a specified number of entries at any given time. You can configure this number using the `Maximum Cache Entries` property. Each stored entry is held in the cache memory for a specific period of time, after which the entry expires and must be processed again. This expiration time is called _time to live_ (TTL).
Another condition that can trigger the expiration of an entry is when the cache reaches the maximum number of items that it can store. When this scenario occurs, the entry is removed by using the FIFO (First-In First-Out) criteria. This means that the earliest entry to reach the cache is removed, even though it hasn’t reached the TTL value yet.
### Distributed Cache
Each entry in the cache can be shared between different nodes in a cluster or between several workers in Runtime Manager using the `Distributed` option (see table). If this option is not enabled, then each node is assigned its own cache memory.
### Persistent Cache
A persistent cache enables the stored entries in the cache to persist if the Flex Replica is restarted.
When you upgrade a version of the instance that has the HTTP Caching policy configured to use the persistent store, the policy tries to maintain the entries stored by the previous version. However in a worst-case scenario, the entries in the cache are invalidated and the cache is re-populated when new requests arrive. This manipulation of the entries in the cache occurs automatically and is invisible to the user.
## HTTP Caching Directives
To obtain more control over the cache, the HTTP Caching policy interprets some of the HTTP directives from the RFC-7234 protocol by taking the following headers into account:
  * `Cache-Control`
  * `Expires`


### Cache-Control
The `Cache-Control` header can exist either in the request or in the response. Possible values for the header, which can be combined separated by commas, include:
  * In requests:


The response is not searched for, but is directly stored in the cache.
The response is not stored in the cache. However, if the response is already present in the cache, the policy returns the response.
  * In responses:
    * `no-store`, `no-cache`, `private`


For each value, the response is not stored in the cache.
  * `max-age=<integer>`, `s-maxage=<integer>`


The `<integer>` placeholder must be replaced with a valid integer that indicates the time (in seconds) for which the response can remain in the cache. If both parameters are defined, `s-maxage` takes precedence over `max-age`.
If a global time-to-live (TTL) value is also defined for the policy, these header values override the global TTL configured in the policy if the time specified in the headers is less than the global TTL.
### Expires
If present, this header specifies the date by which the entry in the cache expires. If you specify the `max-age` directive or `s-maxage` directive, this header is ignored. You must define the header value as stated in RFC-1123.
### Date
The `date` header, as defined per RFC-1123, specifies the date and time when the response is created. If not defined, the `date` header is added with the time when the request was received. This header is used in conjunction with the values defined in the `max-age` and `s-maxage` directives of the Cache-Control header.
The `age` header indicates the time (in seconds) elapsed since the origin of the cached response specified in the date header. This header is calculated by the policy and added to each response that is retrieved from the cache.
The expiration time is calculated using the `cache-control`, `date`, and `expires` headers. However, if the resulting expiration time exceeds the one imposed by the TTL value of the entry, the cache entry expires anyway.
### Invalidate
The `invalidate` header, if configured in the HTTP Caching policy, invalidates the entries in the cache, thereby causing the request to be processed again. You specify the name of the header in the Invalidation Header configuration to turn on the option. The value of the header can take only one of the following options: `invalidate`
This option invalidates the entry whose key matches the current request. `invalidate-all` This option invalidates all the entries from the cache.
For example, imagine that the following values are configured in the policy for the request:
  * `HTTP Caching Key`: "#[attributes.requestPath]"
  * `Invalidation header`: "myInvalidationHeader"


The following command invalidates the entry with key “/my/policy" from the cache:
`curl http://<MyAppURL>/my/policy -H “myInvalidationHeader:invalidate”`
The following request invalidates all entries from the cache:
`curl http://<MyAppURL>/my/policy -H “myInvalidationHeader:invalidate-all”`
## Conditional Caching
Conditional caching enables you to configure a set of conditions that must be met before entries are stored in the cache. If none of the conditional caching parameters are configured, the cache stores the responses for every incoming request. If configured, parameters are evaluated for each request to determine whether the response of the current request must be stored.
For conditional request expressions, only the responses for incoming requests with HTTP methods `GET` or `HEAD` are cached by default. For conditional response expressions, only status codes specified by RFC-7231 are cached by default.
For more information about the default values, see Configuring Policy Parameters.
**What happens when the evaluation of the key results in any error?**
If the evaluation of the expression for a particular request results in an error, the policy does not take effect and the request continues to the next receptor in the policy chain.
**Can I store only part of the response with this policy?**
No, but you can apply a policy before this one and transform the response to something else.
**What happens if one parameter is configured to search for the response in the cache and the other parameter is configured for the opposite action?**
This is the same as configuring the response to be stored in the cache when there is a no-store directive in the Cache-Control header.
In this situation, the response isn’t stored. You must configure both the Cache-Control header and the cache to be able to store and search for the response in the cache.
**What happens if I do not define some of the optional parameters?**
If you have not configured the `invalidation` header, you cannot invalidate the cache in a request. Additionally, if you have not configured the request expression or response expression, the cache is used for all requests and all the responses are stored in the cache (expression #[true]).
**Can I modify the Invalidation header values?**
No, you can modify only the header name.