Composable storefront (aka Spartacus) architecture based on Javascript client application may be very chatty with the SAP Commerce Cloud application server. A proper multi-layer caching strategy is a MUST-HAVE for a good user experience.
Implementing an effective caching policy across the entire system can significantly improve performance, leading to quicker response time, enhanced scalability by increasing the maximum throughput supported by the system, reduce risks of system unavailability and decrease cost associated to Commerce Cloud infrastructure.
Compared to JSP Storefront, using SAP Commerce REST API (aka OCC) is also a massive opportunity to introduce fine-grained caching of the API with a CDN and browser cache.
This document will analyze all the layers of caching and suggest best practices to setup the cache.
If you enable Server-Side Rendering (SSR) on SAP Commerce Cloud composable storefront then caching with a CDN is mandatory to avoid severe degradation of performance.
Cache-control is an HTTP header that specifies the caching policies in client requests and server responses. Policies include how a resource is cached, where it’s cached and its maximum age before expiring (i.e., time to live).
The cache-control header management is key for proper caching.
In SAP Commerce, customers can setup the cache-control header for OCC API to have better control of client-side caching.
The variety of caching headers can make manual cache management overwhelming. CDNs allow for granular cache policy management through a user-friendly dashboard, relieving you of the need to manually tweak individual headers.
In addition to simplifying cache management, CDNs augment the browser caching process using proxies. Proxy caching brings content closer to site visitors, accelerating the delivery of locally stored resources. This is especially beneficial for first-time visitors whose browsers have yet to cache site content.
Composable storefront has currently implemented Server-Side Rendering (SSR) for the following types of pages:
The chosen CDN for Composable Storefront (Cloud Flare, Section IO, Akamai, …) usually offers caching capabilities through two methods:
The CDN can cache the following types of content:
It’s important to note that API results are not cached by default. To enable caching for API results, specific headers or URL patterns must be configured.
Most of the dynamic elements on a page are retrieved through OCC (Omni Commerce Connector) API requests. As a result, it should be feasible to cache most pages, with the exception of core Commerce pages. The caching frequency may vary depending on the specific page and its content.
Setting up a Content Delivery Network (CDN) for a Composable storefront typically involves the following steps:
The above Configuration may vary based on the CDN Provider.
For API endpoints, you need the API domain name to be resolved by your DNS to your CDN and your CDN to proxy the request to your API servers.
Following steps for setting up CDN for API endpoints:
For the remaining configurations, we can adopt the same settings as those used for the composable storefront.
See https://microlearning.opensap.com/media/1_w1q1p6id for an example of setup using Cloudflare.
A cache warm-up strategy for a Content Delivery Network (CDN) involves preloading or populating the CDN cache with frequently accessed content to ensure that it’s readily available when users request it. Here’s a guide to implementing an effective cache warm-up strategy for your CDN:
By implementing a well-planned cache warm-up strategy for your CDN, you can ensure that your content is readily available to users, reduce origin server load, and improve overall website or application performance.
The browser will automatically cache resources by following the Cache-Control directives provided in the HTTP response header.
Please consider this is not possible to invalidate the user’s browser cache. The user must physically clear their browser cache.
We recommended using REDbot (https://redbot.org/) to validate HTTP responses including caching.
Chrome Developer Tools is also a must-have for troubleshooting HTTP headers and responses.
We strongly advise to use a CDN when SSR is enabled in the composable storefront. It is beneficial for several reasons:
In standard, SSR serves anonymous pages such as Home, PLP, PDP and CMS pages. Responses are anonymous for a given deep link (i.e. `/product/123`) and should be cached on a CDN. Fast responses will improve the first visit for new customers as well as affect the ranking for crawlers. This action minimises the server’s workload and reduces the occurrence of CSR fallbacks as much as possible. Go through the help page for the SSR optimisations for more details.
Below are our recommendations for caching for the SAP Commerce Cloud’s most common pages.
Type | CDN Cache Policy | CDN TTL (sec) | URL Pattern(s) | Examples URLs |
The standard setting for Server-Side Rendering (SSR). (Home, PLP, PDP and CMS pages) |
Public | 1800 | ||
The standard setting for Client-Side Rendering (CSR). (Cart, Checkout, My Account, Orders..) |
No-cache |
/cart /orders/* /product-added |
https://*/cart https://*/ca-en/product-added/* https://*/checkout-login https://*/checkout/shipping-address https://*/checkout/delivery-mode https://*/checkout/review-order https://*/order-confirmation https://*/ca-en/checkout/addresshttps://*/my-account/orders https://*/my-account/address-book https://*/my-account/payment-details https://*/USD/my-account/update-profile |
|
Home Page | Force-cache | 3600 | / | |
PDP | Force-cache | 120 | Adapt to your URL patterns | |
Content Page | Force-cache | 3600 | Adapt to your URL patterns | |
PLP | Force-cache | 120 | Adapt to your URL patterns |
In the standard SSR implementation, there’s no cache-control begin added, but this could be customised by customers. See Configuring the SSR Optimization Engine SAP Help Page.
This is a global configuration (not page-level) but it will help when you have no CDN.
For pages served by SRR, if you do not have CDN, consider adding cache control for all pages in the Node Express application that is serving SSR.
To set cache-control for OCC API endpoints, you can use XSS filer, see Injecting Static HTTP Response Headers SAP Help page. XSS filter can be controlled with a far-future expiration header and does not require any fine-grained configuration.
However OCC responses requires different cache-control configurations per endpoint, or even per field response (i.e. `product?fields=name` vs `product?fields=stock`). A structure for OCC responses still makes sense, but the maxAge should be set to the minimum applicable time.
These guidelines delineate the criteria for determining the appropriateness of caching for API responses within a technical context.
Caching Guidelines
Composable Storefront Configuration
Resource Types
CDN and Cache-Control
Cache Flushing
The API comes as standard, and it’s up to the customer to configure its caching settings according to their business needs.
Please find below the recommendations for caching for API endpoints.
Resource | Type | URI | CDN Cache Policy | CDN TTL (sec) | Cache Control | Comment |
Users | GET |
/{baseSiteId}/users /{baseSiteId}/users/{userId} /{baseSiteId}/users/{userId}/customergroups |
Never | N/A | Private | |
Base Sites | GET |
/basesites /{baseSiteId}/countries /{baseSiteId}/countries/{countyIsoCode}/regions |
Same as Cache Control | N/A | Public, 360 sec | The cache control setting is relatively low, and it can be increased beyond the cache control level. |
Base Stores | GET | /{baseSiteId}/basestores/{basestoreUid} | Same as Cache Control | N/A | Public, 120 sec | The cache control setting is relatively low, and it can be increased beyond the cache control level. |
Addresses | GET |
/{baseSiteId}/users/{userId}/addresses /{baseSiteId}/users/{userId}/addresses/{addressId} |
Never | N/A | Private | |
Carts |
GET PUT |
/{baseSiteId}/users/{userId}/carts /{baseSiteId}/users/{userId}/carts/{cartId}/email /{baseSiteId}/users/{userId}/carts/{cartId}/payment/sop/response /{baseSiteId}/users/{userId}/carts/{cartId}/consolidate3600 /{baseSiteId}/users/{userId}/carts/{cartId} /{baseSiteId}/users/{userId}/carts/{cartId}/payment/sop/request |
Never | N/A | No Cache | |
Catalogs | GET |
/{baseSiteId}/catalogs /{baseSiteId}/catalogs/{catalogId} /{baseSiteId}/catalogs/{catalogId}/{catalogVersionId} /{baseSiteId}/catalogs/{catalogId}/{catalogVersionId}/categories/{categoryId} |
To be determined | N/A | No Cache | Verify with the CDN; ideally, it should be eligible for caching at the CDN. |
Component | GET | /{baseSiteId}/cms/components | To be determined | N/A | Public, 3600 sec |
Determine whether the caches are in the regional cache or at the second-level cache Verify with the CDN; ideally, it should be eligible for caching at the CDN. |
Consents | All |
/{baseSiteId}/users/{userId}/consenttemplates /{baseSiteId}/users/{userId}/consenttemplates/{consentTemplateId} |
Same as Cache Control | N/A | Private | |
Customer Groups | All | /{baseSiteId}/customergroups | N/A | N/A | No cache | |
Customers | GET | /{baseSiteId}/customers/logout | N/A | N/A | No cache | |
Export | GET | /{baseSiteId}/export/products | N/A | N/A | No Cache | |
Extended Carts | All | /{baseSiteId}/users/{userId}/carts | N/A | N/A | No Cache | |
Merchant Callbacks | All | /{baseSiteId}/integration | N/A | N/A | ||
Currencies/Languages | GET | /{baseSiteId}/currencies /{baseSiteId}/languages |
Same as Cache Control | N/A | Public, 3600 sec | Need to measure if CDN caching would be an improvement. |
Orders | GET/HEAD |
/{baseSiteId}/orders/{code} /{baseSiteId}/users/{userId}/orders/ /{baseSiteId}/users/{userId}/orders/{code} |
Never | N/A | Public, 120 sec |
Should not be cached
Caching in CDN will result in access to everyone with proper URL (URL easy to be guessed) |
Page | GET | /{baseSiteId}/cms/pages | Same as Cache Control | N/A | Public, 600 sec | Check whether the caches are in the regional cache or the secondary level cache. |
Payment Details | All | /{baseSiteId}/users/{userId}/paymentdetails | N/A | N/A | Private | |
Payment Modes | All | /{baseSiteId}/paymentmodes | Same as Cache Control | N/A | TBD | |
Products | GET |
/{baseSiteId}/products/{productCode} |
Same as Cache Control | N/A | Public, 120 sec |
This is the probably the most important API endpoint to cache as this is very frequently called in Composable Storefront (Carousel on the Home Page, PDP…). Regrettably, Composable Storefront Out of the Box (OOTB) does not have a built-in mechanism to segregate price and stock information from static product data. In Composable Storefront, stock and pricing details are included within the product responses, and there is no distinct endpoint available for retrieving pricing based on a SKU code. |
Products MISC | GET |
/{baseSiteId}/products/{productCode}/reviews /{baseSiteId}/products/suggestions /{baseSiteId}/products/suggestions |
Same as Cache Control | N/A | Public, 300 sec | Verify with the CDN; ideally, it should be eligible for caching at the CDN. |
Stock | GET |
/{baseSiteId}/products/{productCode}/stock /{baseSiteId}/products/{productCode}/stock/{storeName} |
Same as Cache Control | N/A | No Cache | |
Product Listing Page | GET |
/{baseSiteId}/products/search |
Same as Cache Control | N/A | No Cache | |
Promotions | All | /{baseSiteId}/promotions | Same as Cache Control | N/A | Public, 300 sec | |
Save Cart | All | /{baseSiteId}/users/{userId}/carts | Same as Cache Control | N/A | No Cache | |
Sitemap | GET | /{baseSiteId}/sitemap | N/A | N/A | No Cache | |
Stores | GET |
/{baseSiteId}/stores /{baseSiteId}/stores/{storeId} /{baseSiteId}/stores/storescounts /{baseSiteId}/stores/country/{countryIso} /{baseSiteId}/stores/country/{countryIso}/region/{regionIso} |
Same as Cache Control | N/A | Public, 1800 sec | |
Vouchers | GET | /{baseSiteId}/vouchers/ | N/A | N/A | No Cache |
These are the static resources that will be JavaScript, CSS, Images and any other static assets.
The Commerce platform allows for configurable HTTP Headers in the *application layer*, including cache-control.
The default cache policy will be public with a max-age of 1 year.
This value can be overridden for the media web extension using the XSS filter, see Injecting Static HTTP Response Headers SAP Help page. Please note, the value will be the same for all medias.
Consider adding cache-control headers for media with a far future expiration header (i.e. 1 year)
In this case, the cache-control configuration for platform extensions will not affect the static resources for Composable Storefront. Since there’s no backend application involved for those resources, there’s no cache-control (TTL) possible in CCv2 for those resources. Since those resources have unique file names (based on the content hash), the resources can be cached with far-future expiration headers.
Please find below the recommendations for caching for static resources.
Type | CDN Caching Policy | CDN TTL | Cache-Control | URL Pattern | Comment | Examples URLs |
Javascript | Force-cache | 1 Year | N/A | .js | These are given version numbers with each deployment. | */main-*.js |
Images | Force-cache | 1 year | N/A |
/medias/ /images/ |
Anything that includes these patterns should be subject to caching. | |
CSS | Force-cache | 1 Year | N/A | .css | These are given version numbers with each deployment. | */assets/**/SPA_Web_Fonts_2020.css |
fonts | Force-cache | 1 Year | N/A | .eot .woff .otf .woff2 .ttfn.ps |
These are given version numbers with each deployment. | |
svg | Force-cache | 1 Year | N/A | .svg | These are given version numbers with each deployment. | |
Anything | Force-cache | N/A |