Skip to main content

Implement Caching in the Web-Server Layer

Learning Objectives

After completing this unit, you’ll be able to:

  • List the Salesforce B2C Commerce architectural layers.
  • Describe the general logic for when a page contains markers for remote includes.
  • Describe a scenario on a web server where you combine static and dynamic data.
  • Explain why the script API is preferable to templates for caching.

Strategize Caching

The more quickly your site loads, the more likely it is to keep a shopper engaged and lead to a sale. As seconds tick past, other sites and activities clamor for their attention. Each step through an implementation’s architectural layers costs time. An effective caching strategy moves content delivery closer to the shopper, which makes for a faster and more reliable website.

In the B2C world, you want to show data as fast as possible. When a shopper clicks a product tile, for example, the product details must come all the way from the server. The page layout, however, is the same from product to product. If you save the layout in cache on the client, at least part of the page serves fast. Every little bit counts. 

Cache is a reserved storage location that collects data to help websites, browsers, and apps load faster. Whether it’s a computer, laptop, phone, web browser, or app, you have lots of ways to implement caching. Caching affects all layers of an application’s architecture. The more layers an application traverses, the slower the response time and the lower the scalability of the app.

Caching at Cloud Kicks

Linda Rosenberg, an admin at Cloud Kicks, a high-end sneaker company, wants to ensure her B2C Commerce storefront uses every means possible to improve performance. She takes a look at the Headless Implementation Strategies for Salesforce B2C Commerce Trailhead module to understand distributed and in-memory caching for static content and the API layer.

Linda Rosenberg, Cloud Kicks admin

She knows that setting up caching with Salesforce B2C Commerce means a lot more than adding <iscache> tags to a few templates. B2C Commerce manages caching in these architectural layers using different cache methods.

Layer

Caching Method

Web-server

Page Cache

Application-server 

Custom Cache (CacheMgr)


Storage

Custom Attributes or Custom Objects

Caching is so important that each contributor must adopt a mindset whereby they automatically consider how their piece impacts the whole. Let’s look at what can happen with a simple application change.

Cloud Kicks marketing wants to show a heart icon with a red outline for each product on a search result. They want a solid, red heart icon to display for items on the shopper’s wishlist.

Vijay Lahiri, Cloud Kicks developer, simply updates the search results page to render HTML that represents the wishlist state of a given product.

Vijay Lahiri, Cloud Kicks developer

After thinking more about it, Vijay questions his first approach. He doesn't want to bog down the app. While this approach is functionally correct, the application must generate separate search results for each shopper who searches for a product. That means the application must dynamically calculate the information for each product tile, traversing all architectural layers… for every shopper. 

Vijay remembers that wishlist contents don’t change a lot, so he changes his approach to:

  1. Expose the wishlist contents, such as shopper information or login state in the header, as an HTML data attribute in a preexisting dynamic include.
  2. Update the heart icon status using client-side JavaScript.
Note

A dynamic include (the jsp:include tag), dynamically includes output from the included page within the output of the including page, during runtime. This is known as a dynamic include (or runtime include).

On the server side, the new approach adds almost no cost, and the operation on the client side is relatively minor. The approach uses the available layers to achieve great performance and better scalability compared to Vijay’s original, server-side solution.

Web-Server Layer

Page caching happens in the top architectural layer, which is the web-server layer. Server-side includes (SSI) are placeholders in the page for which the web-server layer issues new requests. Each request can have its own cache policy. For example, on a static content page that’s entirely cacheable, Vijay includes dynamic information, such as the shopper’s login state, using a remote include.

While the main request might be cached for a few days, another request is issued that dynamically retrieves the shopper information to display in the header. The sub-request isn’t cached. The web-server tier inserts the dynamically computed piece of the page into the cached frame, resulting in a page that contains both cached and uncached elements. 

The page cache is a key-value store, which is a table with references. The key is the full URL, including the query string, while the value is a reference to the cached page. The page can contain markers for remote includes that are resolved the same way using this general logic.

  1. The client makes the request.
  2. The application checks if the cache entry for the request path exists.
  3. If it does, the application uses the cached response and continues processing remote includes. For each remote include, the application starts at 1.
  4. If it doesn’t, the application calls the application layer to obtain a response.
    • The application checks if the response is marked for caching.
    • If it is, the application saves the data in the page cache.
    • The application returns the response.

Dynamic Parameters in Includes

Avoid adding dynamic parameters to includes, which are likely to change frequently but don’t impact the response. These URLs create different cache entries, with the results computed first, before the cache entry is created. This adds more time, and can (involuntarily) contribute to excessively high cache entries and a lower cache-hit rate.

https://www.domain.com/path?param1=1
https://www.domain.com/path?param1=2 (change in parameter)
https://www.domain.com/path?param1=1&param2=abc (additional parameter)
https://www.domain.com/path?param2=abc&param1=1 (change in parameter order)
https://www.domain.de/path?param1=1 (different domain)
https://www.domain.com/otherpath?param1=1 (different path)

Using a Position Parameter

Vijay’s application adds a position parameter to product tiles in a search result. A position parameter specifies the order in which the tiles display. Each tile is cached many times, depending on its position in the search result, even though the same product always displays. When the shopper navigates search results on the product detail page (PDP), the app must pass search information using the product detail page URL. A better way to pass search information is to implement a client-side solution, which drastically increases search page throughput.

Ignore URL Parameters with No Meaning

B2C Commerce sometimes appends parameters with no meaning to URLs on the page, such as the campaign ID parameter of a newsletter campaign. For caching purposes, you can configure B2C Commerce to ignore these parameters using the Business Manager feature switch, Web Adapter Cache Key Ignore by Query String.

In this module, we assume you are a Salesforce B2C Commerce admin with the proper permissions to perform these tasks. If you’re not a B2C Commerce admin, that’s OK. Read along to learn how your merchandiser takes these steps in a staging instance. Don’t try to follow our steps in your Trailhead Playground, because B2C Commerce isn’t available in the Trailhead Playground.

If you have a development instance of B2C Commerce, you can try out these steps in your instance. If you don’t have a development instance, ask your manager if there is one that you can use.

Enable Caching of 404 Responses

If you want to make your site more scalable, try enabling caching of 404 responses using these steps.

  1. Open Business Manager.
  2. Click Administration > Global Preferences > Feature Switches.
  3. Scroll down, and select Enable 404 response caching overrides.

    In Business Manager, Enable 404 response caching overrides
Note

Realms created after September 15, 2020, have 404 caching enabled by default. Administrators can disable 404 error response caching using feature switches in Business Manager.

Personalized Caching

B2C Commerce provides out-of-the-box personalized caching, which amends the cache key according to the currently active price books and applicable promotions. For example, imagine two shoppers are viewing the same page through the same URL. Shopper A uses price book X, while shopper B uses price book Y. In this case, the same product with the same URL is cached twice. The application serves the shoppers who use price book X a respective cache entry the same way as the application does for shoppers who use price book Y.

Depending on the number of price books and promotions, this scenario can lead to a large increase in cache entries, even if each entry’s product price is different. Use personalized caching only when necessary, for example, when you want to serve different cached content to different parts of your audience.

Scripts and Templates

As a best practice, use the script API instead of the <iscache> tag. The dw.system.Response#setExpires(milliseconds)script API controls the response caching behavior. While both approaches control the caching of the entire response, not individual templates, using the ISML tag presents these challenges.

  • Using the <iscache> tag can be confusing, because it might suggest you are just caching a template.
  • It can be difficult to figure out which template defines the caching behavior of a response, because templates can be nested, with each one having its own <iscache> tag, where the lowest defined cache time is applied.
  • A template can be used in different contexts that require different cache policies, making the implementation complex.

Here are some examples of script API calls.

// SFRA controller cached via decorator
server.get('Show', cache.applyDefaultCache, function (req, res, next) {} );
// Set cache time directly at the response (doesn’t rely on SFRA)
response.setExpires(new Date().getTime() + durationInMinutes * 60 * 1000);
// Apply personalized caching
response.setVaryBy('price_promotion');
// Cache times don’t have to be constants. Get creative!
// Apply layered caching times by product availability levels
var availabilityModel = product.getAvailabilityModel();
if (availabilityModel.isOrderable(50)) {
// Cache 5 days when >= 25 orderable
response.setExpires(new Date().getTime() + 120 * 60 * 60 * 1000);
} else if (availabilityModel.isOrderable(20)) {
// Cache 4 hours when >= 10 orderable
response.setExpires(new Date().getTime() + 4 * 60 * 60 * 1000);
} else {
// Cache 30 minutes when < 10; orderable
response.setExpires(new Date().getTime() + 30 * 60 * 1000);
}
Note

The Storefront Reference Architecture (SFRA) provides decorators you can use instead of dw.system.Response, which apply to preconfigured caching times.

Next Steps

In this unit, you learned why paying attention to caching at every architectural layer is critical for optimal site performance. You also explored caching in the web-server layer. Next, take a deeper look into caching in the application-server and storage layers.

Resources

Keep learning for
free!
Sign up for an account to continue.
What’s in it for you?
  • Get personalized recommendations for your career goals
  • Practice your skills with hands-on challenges and quizzes
  • Track and share your progress with employers
  • Connect to mentorship and career opportunities