The API Platform exposes a Cache resource that can be used at runtime to persist data across transactions.
There are three main reasons for using a cache:
- To reduce latency: The request is satisfied from the cache (which is closer to the client) instead of the origin server, so the cache gets the representation and displays it in a shorter time. This makes the server more responsive.
- To reduce network traffic: Representations are reused, so the impact of processing duplicate or redundant requests is reduced. Cache reduces the amount of bandwidth you use, which decreases bandwidth requirements overall.
- To persist data across transactions: Session data can be stored for reuse across HTTP transactions.
Code sample The sample policies in this reference are based on the Twitter Translate sample proxy in API Platform samples on Github. This sample uses the Cache policy to store an OAuth access token for re-use across multiple outbound calls.
Defining a Cache resource
You can create multiple Cache resources in each environment. For data segregation, the scope of a Cache is limited to an environment in which the Cache is created. (For example, API proxies running in a 'test' environment cannot access data in a Cache running in 'prod'.) Once the Cache is created, it can be populated with any serializable data by using Cache policies.
Note: A default Cache resource is configured for every organization. Under ordinary circumstances, you do not need to explicitly configure a Cache. Only configure a Cache when you need to customize the Cache settings and configuration optimize performance. If you have questions about your Cache resource configuration, contact Apigee Support.
See also Reduce latency using ResponseCache.
Manage Caches using the API Platform API
Create a Cache
Use the API Platform API to create a Cache resource. Caches are created per environment. For data segregation, a Cache created in 'test', for example, cannot be accessed by API proxies deployed in 'prod'.
For example:
$ curl -H "content-type:text/xml" -X POST -d \
'<Cache name="mycache">
<Description>A Cache resource for the test environment.</Description>
<MaxElementsInMemory>100</MaxElementsInMemory>
<MaxElementsOnDisk>1000</MaxElementsOnDisk>
<OverflowToDisk>true</OverflowToDisk>
<Persistent>false</Persistent>
<ExpirySettings>
<TimeoutInSec>300</TimeoutInSec>
</ExpirySettings>
<Compression>
<MinimumSizeInKB>1024</MinimumSizeInKB>
</Compression>
</Cache>' \
https://api.enterprise.apigee.com/v1/o/{org_name}/environments/test/caches \
-u myname:mypass
Configuring a Cache resource
You can configure a Cache resource using the following elements.
| Field Name | Description | |
|---|---|---|
| Description | Description of the Cache resource. | |
| MaxElementsInMemory | Maximum number of Cache entries allowed in memory. Upon reaching the maximum limit, entries are discarded using Least Recently Used (LRU) algorithm. | |
| MaxElementsOnDisk | Maximum number of Cache entries allowed in the disk. Upon reaching the maximum limit, entries are discarded using LRU algorithm. | |
| OverflowToDisk | Valid values: true/false Default value: false If true, the elements discarded from in-memory Cache are stored to a disk Cache. The elements discarded from disk Cache are permanently deleted. |
|
| Persistent | Valid values: true/false Default value: false If true, cache entries are persistent across restarts. Persistence of cache ensures that all cached messages are readily available during the crash-recovery process and therefore, prevents data loss. |
|
| ExpirySettings | TimeoutInSec | Duration (in seconds, ss) to leave for the cached entry. |
| TimeOfDay | A specific time (hh:mm:ss) of day. | |
| ExpiryDate | Specify the date (mm-dd-yyyy). | |
| Compression | MinimumSizeInKB | Optional. If specified, all entries above this size are compressed when stored to disk. |
Example - Cache resource configuration
Update a Cache
To modify the Cache resource created above, issue a complete payload POST request to the same URI as above, except include the name of the Cache resource as a URI parameter
$ curl -H "content-type:text/xml" -X POST -d \
'<Cache name="mycache">
<Description>Updating the Cache.</Description>
<MaxElementsInMemory>100</MaxElementsInMemory>
<MaxElementsOnDisk>1000</MaxElementsOnDisk>
<OverflowToDisk>true</OverflowToDisk>
<Persistent>false</Persistent>
<ExpirySettings>
<TimeoutInSec>300</TimeoutInSec>
</ExpirySettings>
<Compression>
<MinimumSizeInKB>1024</MinimumSizeInKB>
</Compression>
</Cache>' \
https://api.enterprise.apigee.com/v1/o/{org_name}/environments/test/caches/{cache_name} \
-u myname:mypass
View Cache contents
$ curl https://api.enterprise.apigee.com/v1/o/{org_name}/environments/test/caches/{cache_name} \
-u myname:mypass
Delete a Cache entry
$ curl -X DELETE \
https://api.enterprise.apigee.com/v1/o/{org_name}/environments/test/caches/{cache_name}/entries/{cache_entry_key} \
-u myname:mypass
Access the Cache at runtime
One reason why you may need to use the Cache resource is when you have OAuth access tokens that are used for outbound calls from the API Platform to protected backend services. Without a Cache in which to store the OAuth access token, the application would be required to obtain a new access token for each request.
In the following example, an OAuth access token is written to the Cache using PopulateCache and retrieved for subsequent requests by LookupCache, until the access token expires. (Application logic, written in JavaScript executes the logic on top of the Cache.)
For code samples and example Cache policies, see the Twitter Translate sample proxy in API Platform samples.
PopulateCache
The PopulateCache policy type enables you to write data to the Cache. In this example application an OAuth access token is written to the Cache.
The PopulateCache policy below writes the value of the Source to the Cache resource named mycache. The Source in this case is a custom variable named twitter-translate.apiAccessToken.
(Variables can be populated by policies or by code. The Source variable in this example is populated by the following JavaScript call: context.setVariable('twitter-translate.apiAccessToken', getAccessToken());)
The policy also defines a CacheKey, which consists of a KeyFragment. The CacheKey is used as a reference by the LookupCache policy to retrieve the value of the access token. (See Working with CacheKeys.)
<PopulateCache name="token-cache">
<CacheResource>mycache</CacheResource>
<Source>twitter-translate.apiAccessToken</Source>
<Scope>Exclusive</Scope>
<CacheKey>
<KeyFragment>apiAccessToken</KeyFragment>
</CacheKey>
<ExpirySettings>
<TimeoutInSec>600</TimeoutInSec>
</ExpirySettings>
</PopulateCache>
Configuring the PopulateCache policy
Configure the PopulateCache policy using the following elements.
| Field Name | Description | |
|---|---|---|
| CacheResource | Specifies the Cache resource to be used. | |
| Source | Identifies the variable from which the Cache value will be read. | |
| Scope |
Used to create a namespace for data in the Cache. Supported settings are Global, Application, Proxy, Target, Exclusive. |
|
| CacheKey | Prefix |
Used to create a namespace for data in the Cache. CacheKey is used by LookupCache policy to reference Cached data. The structure of a CacheKey is
{Scope/Prefix}__{KeyFragment}__{KeyFragment}__{KeyFragment} . . .You can define as many KeyFragments as needed to prevent namespace collisions in your cached data. If defined, the value of
Prefix used as the prefix value of the CacheKey for entries written to the Cache. Prefix overrides Scope elements. |
| KeyFragment |
A
KeyFragment can either contain a key (a static name that you provide) or a value (a dynamic entry set by referencing a variable).KeyFragment elements are prepended with
Prefix and concatenated to define the CacheKey. For example, where Prefix is set to UserToken), and 2 KeyFragments are defined as follows:
<CacheKey>
<Prefix>UserToken</Prefix>
<KeyFragment>apiAccessToken</KeyFragment>
<KeyFragment>{request.queryparam.client_id}</KeyFragment>
</CacheKey>
The result is a CacheKey of |
|
| ExpirySettings | TimeoutInSeconds | Duration (in seconds) to live for the cached entry. |
| TimeOfDay | A specific time (hh:mm:ss) of day. | |
| ExpiryDate | Specify the date (mm-dd-yyyy). | |
LookupCache
Once values are populated in the Cache, a corresponding LookupCache policy can be configured to retrieve cached data at runtime. The following LookupCache policy reads from the Cache resource named mycache and writes the value to the variable twitter-translate.apiAccessToken.
<LookupCache enabled="true" continueOnError="false" async="false" name="token-cache">
<CacheResource>mycache</CacheResource>
<AssignTo>twitter-translate.apiAccessToken</AssignTo>
<Scope>Exclusive</Scope>
<CacheKey>
<KeyFragment>apiAccessToken</KeyFragment>
</CacheKey>
</LookupCache>
Configuring the LookupCache policy
Configure the LookupCache policy using the following elements.
| Field Name | Description | |
|---|---|---|
| CacheResource | Specifies the Cache resource to be used. | |
| AssignTo | Specifies the variable where the Cache entry is assigned after it has been retrieved from the Cache. Note that the variable must have write permissions. | |
| Scope |
Used to construct the |
|
| CacheKey | Prefix |
Used to create a namespace for matching requests to the cached responses.
If defined, the value of
Prefix used as the prefix value of the CacheKey for entries written to the Cache. Any Prefix element that is defined overrides Scope settings. |
| KeyFragment |
A
KeyFragment can either contain a key (a static name that you provide) or a value (a dynamic entry set by referencing a variable).KeyFragment elements are prepended with
Prefix and concatenated to define the CacheKey. For example, where Prefix is set to UserToken), and 2 KeyFragments are defined as follows:
<CacheKey> <Prefix>UserToken</Prefix> <KeyFragment>apiAccessToken</KeyFragment> <KeyFragment>request.queryparam.client_id</KeyFragment> </CacheKey> The result is a CacheKey of |
|
InvalidateCache
The Cache resource can be invalidated explicitly by specifying an HTTP header. When a request that contains the specified HTTP header is received, the Cache is flushed.
<InvalidateCache name="InvalidateMyCache">
<CacheResource>mycache</CacheResource>
<Scope>Exclusive</Scope>
<CacheKey>
<Prefix>apiAccessToken</Prefix>
<KeyFragment ref="request.header.invalidate_cache" />
</CacheKey>
<PurgeChildEntries>true</PurgeChildEntries>
</InvalidateCache>
Configuring the InvalidateCache policy
Configure the InvalidateCache policy using the following elements.
| Field Name | Description | |
|---|---|---|
| CacheResource (Optional) | Specifies the name of the Cache resource to be used. | |
| Scope (Optional) |
Used to construct the prefix, when Prefix in CacheKey is not provided. If Prefix is provided, then Scope is ignored. Allowed values are Global, Application, Proxy, Target, and Exclusive. |
|
| CacheContext (Optional) | Application |
Used to construct the CacheKey. |
| Proxy | ||
| Target | ||
| CacheKey (Optional) | Prefix |
Used to create a namespace for matching requests to the cached responses.
If defined, the value of
Prefix used as the prefix value of the CacheKey for entries written to the Cache. Any Prefix element that is defined overrides Scope settings. |
| KeyFragment |
A
KeyFragment can either contain a key (a static name that you provide) or a value (a dynamic entry set by referencing a variable).KeyFragment elements are prepended with
Prefix and concatenated to define the CacheKey. For example, where Prefix is set to UserToken), and 2 KeyFragments are defined as follows:
<CacheKey> <Prefix>UserToken</Prefix> <KeyFragment>apiAccessToken</KeyFragment> <KeyFragment>request.queryparam.client_id</KeyFragment> </CacheKey> The result is a CacheKey of |
|
| PurgeChildEntries (Optional) | Valid values: true/false Default value: false |
|
Working with CacheKeys
CacheKeys can be used to control how your data is stored in the Cache. A CacheKey is a unique pointer to a piece of data stored in the Cache. As such, the CacheKey you define constructs the name of each piece of data stored in the Cache. The CacheKey you define in the PopulateCache policy will be the name that you use in the corresponding LookupCache policy to get the specific entry that you need from the Cache.
A very simple example of a CacheKey is the following:
<CacheKey> <KeyFragment>hello</KeyFragment> <KeyFragment>world</KeyFragment> <CacheKey>
The string value of the CacheKey is a list of KeyFragment values separated by two underscores: hello__world.
The rest of the CacheKey is defined by either a Scope or Prefix. The Scope element is designed to be used as a default Prefix for CacheKeys. Scopes can be defined with increasing specificity from Global to Exclusive.
Where the API proxy is deployed in the 'apigee' organization and deployed in the environment named 'prod', the Scope is apigee__prod__.
Combine the KeyFragment and the Scope to derive the CacheKey: apigee__prod__hello__world.
To use the same CacheKey in different environments, without risking conflicts, you can use the Global Scope. Returning to the example above, the final values for the default environments 'test' and 'prod' would be apigee__test__hello__world and apigee__prod__hello__world, respectively. The CacheKey configuration is the same, but refers to different data depending on the runtime environment in which the cache policy executes.
Once the CacheKey has been combined with the Scope, the final value is not a CacheKey, but rather is an unambiguous identifier for that CacheKey/Scope combination.
A Global scope generalizes a Cache entry across an environment in an organization. Each Cache entry with a Global scope is prefixed with orgName__envName__. Therefore, if you define a CacheKey entry with the KeyFragment apiAccessToken and a Global Scope, each entry is stored as orgName__envName__apiAccessToken, followed by the serialized value of the access token. For an API proxy deployed in an environment called 'test' in an organization called 'apifactory', access tokens would be stored under the following CacheKey: apifactory__test__apiAccessToken.
An Exclusive Scope is the most specific Scope, and therefore presents minimal risk of namespace collisions within a given Cache. Each Cache entry with an Exclusive scope is prefixed with orgName__envName__apiProxyName__deployedRevisionNumber__proxyOrTargetName__[serializedCacheKey]. A sample CacheKey using Exclusive Scope would look like the following: apifactory__test__weatherapi__16__default__apiAccessToken.
- Global: CacheKey prepended with
orgName__envName__ - Application: CacheKey prepended
orgName__envName__apiProxyName - deployedRevisionNumber: CacheKey prepended with
orgName__envName__apiProxyName__deployedRevisionNumber - Proxy: Cache key prepended with
orgName__envName__apiProxyName__deployedRevisionNumber__proxyEndpointName - Target: Cache key prepended with
orgName__envName__apiProxyName__deployedRevisionNumber__targetEndpointName - Exclusive: Cache key prepended with
orgName__envName__apiProxyName__deployedRevisionNumber__proxyOrTargetName__[serializedCacheKey], whereserializedCacheKeyis composed of KeyFragment elements, separated by__(two underscores).
You can have multiple KeyFragments that can either have an explicit value (for example,
To include a variable in the Cache Key, identify the variable as a reference in the KeyFragment. For example, to make the CacheKey unique to the Content-Type of the request message, you could set <KeyFragment ref="request.header.Content-Type"/>, which defines a KeyFragment as the value of the context variable request.header.Content-Type.
For example, in the configuration below, the request.header.Content-Type variable has the value application/json.
<CacheKey> <KeyFragment>apiAccessToken</KeyFragment> <KeyFragment ref="request.header.Content-Type" /> <KeyFragment>bar</KeyFragment> </CacheKey>
The result a CacheKey of {Scope}__apiAccessToken__application/json__bar.
If you require an explicit namespace, then use Prefix instead of Scope. Prefix overrides any Scope settings. The Lookup Cache policy that retrieves data from the Cache must refer to the specific Prefix and KeyFragment structure to retrieve data from the Cache.
Cache Flow variables
Flow variables can be used to configure dynamic runtime behavior for policies and flows, based on HTTP headers or message content, or the context available in the Flow. For more information about flow variables, see Variables reference.
The following predefined Flow variables are available after you customize the behavior of the Cache you define in a LookupCache policy.
| Variables | Type | Permission | Description |
|---|---|---|---|
| lookupcache.<policy-name>.cachename | String | Read-Only | Returns the cache name used in the policy. |
| lookupcache.<policy-name>.cachekey | String | Read-Only | Returns the key used. |
| lookupcache.<policy-name>.cachehit | Boolean | Read-Only | True if the policy execution is successful. |
| lookupcache.<policy-name>.assignto | String | Read-Only | Returns the variable to which cache is assigned. |
Policy schema
Each policy must conform to a policy schema. All policy constructs such as elements and attributes mentioned above are defined in a schema. To download the schema, click here.