b2c-custom-caches

Custom caches improve code performance by storing data that is expensive to calculate, takes a long time to retrieve, or is accessed frequently. Caches are defined in JSON files within cartridges and accessed via the Script API.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "b2c-custom-caches" with this command: npx skills add salesforcecommercecloud/b2c-developer-tooling/salesforcecommercecloud-b2c-developer-tooling-b2c-custom-caches

B2C Custom Caches

Custom caches improve code performance by storing data that is expensive to calculate, takes a long time to retrieve, or is accessed frequently. Caches are defined in JSON files within cartridges and accessed via the Script API.

When to Use Custom Caches

Use Case Example

Expensive calculations Check if any variation product is on sale for base product display

External system responses Cache in-store availability or prices from external APIs

Configuration settings Store configuration data from JSON files or external sources

Frequently accessed data Product attributes, category data, site preferences

Limitations

Constraint Value

Total memory per app server ~20 MB for all custom caches

Max caches per code version 100

Max entry size 128 KB

Supported value types Primitives, arrays, plain objects, null (not undefined )

Cross-server sync None (caches are per-application-server)

Defining a Custom Cache

File Structure

my_cartridge/ ├── package.json # References caches.json └── caches.json # Cache definitions

package.json

Add a caches entry pointing to the cache definition file:

{ "name": "my_cartridge", "caches": "./caches.json" }

caches.json

Define caches with unique IDs and optional expiration:

{ "caches": [ { "id": "ProductAttributeCache" }, { "id": "ExternalPriceCache", "expireAfterSeconds": 300 }, { "id": "SiteConfigCache", "expireAfterSeconds": 60 } ] }

Property Required Description

id

Yes Unique ID across all cartridges in code version

expireAfterSeconds

No Maximum seconds an entry is retained

Using Custom Caches

Script API Classes

Class Description

dw.system.CacheMgr

Entry point for accessing defined caches

dw.system.Cache

Cache instance for storing and retrieving entries

Basic Usage

var CacheMgr = require('dw/system/CacheMgr');

// Get a defined cache var cache = CacheMgr.getCache('ProductAttributeCache');

// Get value (returns undefined if not found) var value = cache.get('myKey');

// Store value directly cache.put('myKey', { data: 'value' });

// Remove entry cache.invalidate('myKey');

Recommended Pattern: get with Loader

Use get(key, loader) to automatically populate the cache on miss:

var CacheMgr = require('dw/system/CacheMgr'); var Site = require('dw/system/Site');

var cache = CacheMgr.getCache('SiteConfigCache');

// Loader function called only on cache miss var config = cache.get(Site.current.ID + '_config', function() { // Expensive operation - only runs if not cached return loadConfigurationFromFile(Site.current); });

Scoped Cache Keys

Include scope identifiers in keys to separate entries by context:

var CacheMgr = require('dw/system/CacheMgr'); var Site = require('dw/system/Site');

var cache = CacheMgr.getCache('ProductCache');

// Site-scoped key var siteKey = Site.current.ID + '_' + productID; var productData = cache.get(siteKey, loadProductData);

// Catalog-scoped key var catalogKey = 'catalog_' + catalogID + '_' + productID; var catalogData = cache.get(catalogKey, loadCatalogData);

// Locale-scoped key var localeKey = request.locale + '_' + contentID; var content = cache.get(localeKey, loadLocalizedContent);

Cache Methods

Method Description

get(key)

Returns cached value or undefined

get(key, loader)

Returns cached value or calls loader, stores result

put(key, value)

Stores value directly (overwrites existing)

invalidate(key)

Removes entry for key

Best Practices

Do

  • Use get(key, loader) pattern for automatic population

  • Include scope (site, catalog, locale) in cache keys

  • Set appropriate expireAfterSeconds for time-sensitive data

  • Handle cache misses gracefully (data may be evicted anytime)

  • Use descriptive cache IDs

Don't

  • Include personal user data in cache keys (keys may appear in logs)

  • Store Script API objects (only primitives and plain objects)

  • Rely on cache entries existing (no persistence guarantee)

  • Expect cross-server cache synchronization

  • Store undefined values (use null instead)

Cache Invalidation

Caches are automatically cleared when:

  • Any file in the active code version changes

  • A new code version is activated

  • Data replication completes

  • Code replication completes

Manual invalidation only affects the current application server:

var cache = CacheMgr.getCache('MyCache');

// Invalidate single entry (current app server only) cache.invalidate('myKey');

// Storing undefined has same effect as invalidate cache.put('myKey', undefined);

Common Patterns

Caching External API Responses

var CacheMgr = require('dw/system/CacheMgr'); var LocalServiceRegistry = require('dw/svc/LocalServiceRegistry');

var priceCache = CacheMgr.getCache('ExternalPriceCache');

function getExternalPrice(productID) { return priceCache.get('price_' + productID, function() { var service = LocalServiceRegistry.createService('PriceService', { createRequest: function(svc, args) { svc.setRequestMethod('GET'); svc.addParam('productId', args.productID); return null; }, parseResponse: function(svc, response) { return JSON.parse(response.text); } });

    var result = service.call({ productID: productID });
    return result.ok ? result.object : null;
});

}

Caching Expensive Calculations

var CacheMgr = require('dw/system/CacheMgr');

var saleCache = CacheMgr.getCache('ProductSaleCache');

function isProductOnSale(masterProduct) { return saleCache.get('sale_' + masterProduct.ID, function() { var variants = masterProduct.variants.iterator(); while (variants.hasNext()) { var variant = variants.next(); if (isInPromotion(variant)) { return true; } } return false; }); }

Configuration Cache with Site Scope

var CacheMgr = require('dw/system/CacheMgr'); var Site = require('dw/system/Site'); var File = require('dw/io/File'); var FileReader = require('dw/io/FileReader');

var configCache = CacheMgr.getCache('SiteConfigCache');

function getSiteConfig() { var siteID = Site.current.ID;

return configCache.get(siteID + '_config', function() {
    var configFile = new File(File.IMPEX + '/src/config/' + siteID + '.json');
    if (!configFile.exists()) {
        return null;
    }

    var reader = new FileReader(configFile);
    var content = reader.getString();
    reader.close();

    return JSON.parse(content);
});

}

Troubleshooting

Issue Cause Solution

Cache not found exception Cache ID not defined in any caches.json Add cache definition to caches.json

Duplicate cache ID error Same ID used in multiple cartridges Use unique IDs across all cartridges

Entry not stored Value exceeds 128 KB limit Reduce data size or cache subsets

Entry not stored Value contains Script API objects Use only primitives and plain objects

Unexpected cache misses Different app server or cache cleared Always handle misses gracefully

Check the custom error log and custom warn log for cache-related messages.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.