Response Caching
Types of Cache
Response Cache
Response Cache (RC) is a file system based cache. It is used in development and production environments for caching HTML and PDF responses, as well as some images. This is a public cache and does not cache user-specific responses.
Response cache is enabled in production and in development environments. However, caching of some resources is handled differently in production and in development environments (see Resource Types).
There are two handlers in response cache - one for images, and another one for pages (HTML and PDF responses). When DXP2 starts processing HTTP request, it checks both handlers if they have the requested resource in their cache. If resource has been found in cache, and it is not stale (has not expired) it may be served to the client, if it passes all the other release conditions of the handler (see the next section).
Images Handler
Cached images are stored in the .images
subdirectory of the site directory and have a tree-like structure which corresponds to the public URL of the underlying image, or it's transformed variant.
.images
└── files
└── images
├── components
│ └── main-logo.jpg
│ ├── main-logo.jpg
│ ├── main-logo.jpg?h=500&s=exact&w=500
│ └── main-logo.jpg?h=600&s=exact&w=600
└── pages
├── home
│ ├── step-1.jpg
│ │ └── step-1.jpg
│ ├── step-2.jpg
│ │ └── step-2.jpg
Caching conditions
In production environments images will be cached only if all the following conditions are met:
- The request is a
GET
request - Image exists (HTTP response code is
200
) - At least one transformation was applied to the image
In development environments all images will be cached in response cache.
Cache release conditions
Cached images will be released from cache if the following release conditions are met:
- The request is a
GET
request - The request is not a
no-cache
request - Cached image is not stale (not expired)
Dynamic Response Cache (pages)
HTML and PDF responses are stored in the site directory under .cache/response
subdirectory and have a tree-like structure which corresponds to the public URL of the underlying page. Each hostname has its own version of cache, as the hostnames may be attributed to different environments and potentially different templates.
response
└── corednacom.coredna.site
├── services
│ └── saas-platform
│ └── _content-management-system
├── _contact-us
├── _about-us
└── __root
Caching conditions
Dynamic resources will be cached only if all the following conditions are met:
- The request is a
GET
request - Page exists (HTTP response code is
200
) - User is not logged in
- Response is either HTML or PDF, or XML
- Page caching is not explicitly prohibited by the framework or in the template
- URL path is not in the exclusions list (configured in the DXP)
Cache release conditions
Cached images will be released from cache and served to the clients, if the following release conditions are met:
- The request is a
GET
request - The request is not a
no-cache
request - Cached image is not stale (not expired)
- User is not logged in
Bypassing Response Cache
The no-cache
Requests. Hard Reload
Response cache respects no-cache
requests. If the client (browser) sends Cache-Control: no-cache
header, such request will bypass response cache and a fresh copy of the requested resource will be served. Most browsers send no-cache
requests when doing hard reload. Hard reload is usually done by holding Shift
(or Ctrl
+Shift
) while refreshing the page, or disabling cache in Developer Tools, or right-clicking on the "Refresh" button and selecting "Hard Reload".
This enables an easy way to bypass response cache, which is handy, especially in development mode when it is important to see the actual.
Authenticated Users
Response cache is a public cache and does not store content for authenticated users. To effectively bypass response cache for dynamic content (i.e. pages), it is sufficient to login as some user. Authenticates users bypass response cache on content URLs, but not the images.
Response Cache HTTP Headers
Hit or Miss
Response Cache sends X-Cache-Status
HTTP header to indicate if the request had hit response cache and a cached version of resource was served.
The possible values are:
X-Cache-Status: miss, no-store
Request missed cache and the current response will not be stored in the response cache due to failing some caching condition (e.g. user is logged in).
X-Cache-Status: miss, store
Request missed cache, but the current response will be stored in the response cache and in the future may be served from cache. In such situation Cache-Control
header will indicate TTL in the max-age
parameter.
X-Cache-Status: hit
Request hit response cache and HTTP response was served from response cache. HTTP response headers will also include Cache-Control
and the Age
headers, indicating the TTL and the age of the resource.
For example:
X-Cache-Status: hit
Cache-Control: private, max-age: 3600
Age: 1200
The headers above indicate a cache hit. The "freshness" of resource is set to 3600 seconds (1 hour) and the current age of the cached resource is 1200 seconds (20 minutes). In 40 minutes times this resource will become stale and will be revalidated.
Varying Parameters in the URL and Variants
By default, the requested resource is matched only by the path in the URL, disregarding a query string. The following two requests will hit the same key in response cache: /my-page
and /my-page?foo=bar
. This improves cache efficiency when request parameters are only used in Javascript (e.g. to track marketing campaigns). However, if request parameter affects the content rendered by a template, this parameter becomes a vary parameter, and it's value is included in the key used for caching. There may be more than one vary parameter for a request - in this case a separate variant of response is created for each combination of vary parameters.
A parameter is automatically considered a vary parameter when it is accessed in a template which is used to render response: {$_request->getParameter('foo')}
. It is also possible to explicitly specify a list of vary parameters using the $_response
helper:
{$_response->setCacheVaryParameters(['foo','color','size'])}
This is particularly useful when some parameters are used within a condition which uses another parameter:
{if $_request->getParameter('foo')=='bar'}
{$color = $_request->getParameter('color')}
{/if}
It is important that the cache is aware of all request parameters used to process the request and render response because all vary parameters are recorded in the cache file (see Cache File Structure). When request is processed by response cache handler, at first, the cache record without parameters is loaded. Then vary parameters are read from that base record and any parameters provided with the requests are matched against vary parameters and the variant record is loaded from cache.
For more information about controlling cache from the templates see Cache Controls in Templates.
Cacheable Response Headers
The following response headers will be cached:
- Content-Type
- Content-Length
- Cache-Control
- Accept-Ranges
- ETag
- Content-Security-Policy
- X-CDN-Key
- X-Source
Cache file structure
Cache file stores cached content, headers, vary parameters and cache expiry information in a JSON structure.
{
"headers": {
"Content-Type": "text/html; charset=UTF-8",
"Cache-Control": "max-age=604800, private"
},
"varyParams": [],
"content": "PGgxPkZvb3RlcjogMTg6MTI6MjM8L2gxPg==",
"expiry": {
"date": "2022-01-15 07:12:23.000000",
"timezone_type": 1,
"timezone": "+00:00"
},
"created": {
"date": "2022-01-08 07:12:23.094162",
"timezone_type": 3,
"timezone": "UTC"
}
}
CDN Cache
CDN cache is a geographically distributed cache which allows serving HTTP responses from the most proximate geographical location to the user. There are 45 points of presence (POPs) around the world. Each POP has its own cache storage. The same request may hit cache is one location, but miss in another.
In development mode CDN caching is disabled. In production mode CDN caching is enabled for all virtual files (including transformed images) and static files, and it can also be enabled for dynamic content in the DXP (see Resource Types).
CDN Headers
When CDN cache is enabled, the response cache will send the appropriate headers to the CDN to indicate that resource is public and cacheable.
Also, it will send X-CDN-Key
response header with a unique CDN key which identifies the site, the environment and the class of the resource. Here is an example of the value of such header:
corednacom.1.2.d
│ │ │ └─ indicates "dynamic" resource
│ │ └─ Environemnt ID
│ └─ Site ID
└─ Config Instance name
Resource Types
There are three main resource classes: dynamic content, virtual files and static files. Each class has different caching rules and supports different types of caching.
Dynamic Content
Dynamic content is the content served by the CMS as HTML, PDF or JSON responses. JSON responses are currently not cached at all. HTML and PDF responses are cached with Response Cache. The TTL setting is controlled in the DXP (System
-> Global Settings
), and by default it is 1 week. It is possible to enable CDN caching for dynamic resources using a switch in the DXP. If CDN cache is enabled, the same TTL settings will be applied to the CDN cache. Dynamic cache can be also controlled in the templates (see the corresponding section).
It is important to mention that due to the limitations of Stackpath CDN, caching of dynamic resources is not compatible with WAF, so WAF must be disabled for the sites which cache pages on the CDN.
Also, it is important to ensure that the "Lifetime" setting in Stackpath is set to "Origin Controlled", otherwise it will not be possible to control TTL value from the DXP.
Virtual Files (including images)
All files managed via File Manager module are the virtual files. All virtual files are cached on CDN. The TTL setting is controlled in the DXP (System
-> Global Settings
). The default TTL for virtual files is 6 weeks. Normally, the virtual files are not cached with file system based Response Cache, given the files are delivered from the file system anyway. However, there are two exceptions:
- Transformed Images. Image transformations (resizing, change of format, etc.) are processed by one of the external providers and this process can be quite slow. CDN keeps caches in 45 separate locations worldwide, and a first request from each new location will be a cache miss. Having Response Cache as the second layer of caching addresses this issue.
- Development environments. In development environments the virtual files are located on the geographically distant network drive, and a network latency may be an issue. Caching virtual files with the local Response Cache in development environments reduces the latency.
Static Files
Static files are the files committed into the website's repository. They are served from the local file system in both, production and development environments, and do not need file based caching. In production environments the static files are cached on CDN with the TTL of 365 days.
A Summary Table with Resource Classes and How they are Cached
Virtual File Type | Production | Development | CDN Key | Invalidated By |
---|---|---|---|---|
HTML response | RC, CDN* | RC | {config}.{site_id}.{environment_id}.d |
Content Update, VCS push, Framework Deploy |
PDF response | RC, CDN* | RC | {config}.{site_id}.{environment_id}.d |
Content Update, VCS push, Framework Deploy |
JSON response | - | - | - | - |
Original Image | CDN | RC | {config}.{site_id}.{environment_id}.f |
Image revision update |
Transformed Image | RC, CDN | RC | {config}.{site_id}.{environment_id}.f |
Image revision update |
Virtual File | CDN | RC | {config}.{site_id}.{environment_id}.f |
Image revision update |
Static File (VCS) | CDN | - | {config}.{site_directory}.s |
VCS push |
Cache Controls in the Templates
There several aspects of caching which are possible to control from the template code.
Cache Expiry
It is possible to explicitly set cache expiry time either from a date/time string with an optional string format or DateTime object:
{$_response->setCacheExpiryDateFromString('2022-12-31 23:59:59')}
{$_response->setCacheExpiryDateFromString('23h 15m 03s', 'H\h i\m s\s')}
{$_response->setCacheExpiryDate($date)}
Also, it is possible to set Cache Time to Live (TTL) value relative to the current time, in seconds:
{$_response->setCacheTTL(300)}
The instruction above will set response cache expiry time to 5 minutes from now.
Vary Parameters
Vary parameters are automatically set whenever $_request->getParameter()
method is called:
{$_request->getParameter('foo')}
{$_request->getParameter('lang')}
It is also possible to explicitly specify the list of vary parameters using $_request->addCacheVaryParameter($paramName)
or $_request->setCacheVaryParameters($params)
which accepts an array of parameter names:
{$_response->setCacheVaryParameters(['foo','lang'])}
Caching Prevention
Caching of the current response can be prevented by calling:
{$_response->preventCaching()}