spring:
cache:
type: none
caffeine-ehcache-since 2.1.6|2.2.2|2.3.0
Out of the box, Broadleaf leverages Spring Cache to handle caching concerns throughout the services. We support multiple caching providers, each optimized for different use cases:
Caffeine (Recommended): A high-performance, near-optimal in-memory caching library. This operates on-heap and is the recommended choice for almost all Broadleaf deployments.
Compact - Leveraging Apache Fury for extremely fast, compact serialization, Caffeine provides highly efficient in-memory storage while maintaining the lowest possible latency. Apache Fury generally achieves a compression factor of 2x to 5x compared to standard Java serialization or raw on-heap object overhead.
Observable - A significant advantage of this approach is that it allows for precise byte-size measurements, ensuring that the Budget Manager’s heap allocations are based on actual data footprint rather than rough estimates. OpenTelemetry observation of cache metrics also benefits from this precision.
Fast GC - With modern garbage collectors like G1 (typically used for heaps up to 32 GB), managing this serialized on-heap cache is highly performant and stable.
Horsepower - Caffeine is ~200x times faster than ehcache and ~475 times faster than ignite in the lab using the same raw IO test.
Ehcache: A robust caching provider configured to support off-heap storage. This remains a viable option for specialized scenarios involving exceptionally large datasets that exceed typical heap recommendations, but for most standard commerce workloads, Caffeine is superior.
Apache Ignite: A legacy option using off-heap native memory. Ignite is deprecated in favor of Caffeine or Ehcache.
For backward compatibility, Ignite remains the default for 2.1.x and 2.2.x. Caffeine is the default for 2.3.x, and beyond.
|
| Most caches in Broadleaf operate in a local, non-distributed mode, and leverage TTL alone for cache eviction. Based on need, cache members can be evicted explicitly based on application events by introducing event handlers that interact with the cache API. |
The out-of-box caching is enabled by default. If for some reason you have the following property declared, you’ll want to remove it.
spring:
cache:
type: none
When caching is enabled, you can explicitly choose which cache manager implementation to use by setting the com.broadleafcommerce.cache.activeCacheManagerImplementation property. Otherwise, the default for your release train version will be used.
The available out-of-the-box options are:
Apache Ignite (Default < Release Train 2.3): com.broadleafcommerce.common.extension.autoconfigure.IgniteCacheAutoConfiguration
Caffeine (Default >= Release Train 2.3): com.broadleafcommerce.common.extension.cache.caffeine.CaffeineAutoConfiguration
Ehcache: com.broadleafcommerce.common.extension.cache.ehcache.EhcacheAutoConfiguration
com:
broadleafcommerce:
cache:
activeCacheManagerImplementation: com.broadleafcommerce.common.extension.cache.caffeine.CaffeineAutoConfiguration
To introduce your own custom cache manager, you can define your own configuration class and set its fully qualified class name as the value for this property. At this point, the out-of-the-box cache manager will be disabled and you can supply your own CacheManagerCustomizer instances.
By default, Caffeine is configured to consume up to 1000MB (1GB) of heap memory for all caches running in the JVM. You can adjust this and enable or disable metrics:
broadleaf:
cache:
caffeine:
heap: 1000 # Maximum size of the on-heap tier in megabytes
metrics-collection-enabled: true # Exports basic metadata (like cache size) to Micrometer
cache-statistics-enabled: true # Tracks throughput metrics (hits, misses, evictions). Requires metrics-collection-enabled=true
Ehcache is configured with both an on-heap tier and an off-heap tier. By default, it allocates 300MB on-heap and 700MB off-heap.
broadleaf:
cache:
ehcache:
heap: 300 # Maximum size of the on-heap tier in megabytes
offheap: 700 # Maximum size of the off-heap tier in megabytes
metrics-collection-enabled: true # Exports basic metadata (like cache size) to Micrometer
cache-statistics-enabled: true # Tracks throughput metrics (hits, misses, gets, puts). Requires metrics-collection-enabled=true
For each application, by default, Ignite is configured to consume up to 1GB of RAM outside the application heap (in native memory) - i.e. the RAM allocated to the application heap should remain the same.
If needed, memory allocation settings can be configured easily via application properties. Please see the Ignite cache node properties documentation for more details.
Broadleaf utilizes Apache Fury for high-performance, compact serialization within the Caffeine and Ehcache providers. For security, Fury requires an allow-list of classes that are permitted for serialization.
While Broadleaf provides a comprehensive standard-allow-list covering framework and common Java classes, you may need to register your own custom domain or DTO classes if they are being cached.
com:
broadleafcommerce:
serialization:
convert:
# Additional classes or packages to allow for serialization
additional-allow-list:
- 'com.yourcompany.domain.*'
- 'com.yourcompany.dto.**'
# Thread pool settings for serialization
min-pool-size: 10
max-pool-size: 20
expire-time-seconds: 30
clone:
# Thread pool settings for deep cloning
min-pool-size: 10
max-pool-size: 20
expire-time-seconds: 30
Use additional-allow-list rather than overriding standard-allow-list to ensure framework-level serialization continues to function correctly.
|
Broadleaf uses a "Budget Manager" concept (CaffeineBudgetManager and EhcacheBudgetManager) to intelligently distribute your total memory limits across all the caches that need it. The notable exception is Ignite, for which we do not carve out individual cache regions in off-heap, and therefore do not establish a budget. While the default for backward compatibility, Ignite is largely deprecated in favor of the other more stable and performant options (Caffeine is recommended for almost all cases).
This is especially important in deployments where multiple Broadleaf services are composed together into a single JVM (such as a Flex package or Monolithic deployment). In these scenarios, multiple services register their memory requests with the Budget Manager.
How it works:
Service Registration: Each service registers its desired memory budget (e.g., 100MB for Catalog, 50MB for Pricing).
Cache Registration: Each service registers its specific cache regions (e.g., CatalogCache, SkuCache) with a weight hint and a TTL.
Normalization: The Budget Manager tallies all requested budgets and compares them against the global properties (like broadleaf.cache.caffeine.heap). If the total requests exceed the global limit, the Budget Manager proportionally scales down the allocations for every service.
Distribution: Within a service, the finalized budget is distributed to individual caches based on their registered weight hints. 90% of a cache’s budget goes to the primary data region, and 10% goes to a companion keys region used for invalidation tracking.
When extending or customizing caching in Broadleaf, you can interact with the BudgetManager (e.g., CaffeineBudgetManager) inside your CacheManagerCustomizer bean to register your new caches and define their TTL and weight.
While services register default weight hints (and estimated sizes for Ehcache), you can override these values via application properties if your specific data patterns require a different distribution. Each service typically exposes property classes (e.g., FulfillmentCacheWeightProperties and FulfillmentCacheSizeProperties) that allow for fine-grained control.
Example Weight Override:
# Give more weight to the pricing config cache in Fulfillment
broadleaf.fulfillment.cache.weights.fulfillment-pricing-config=0.5
broadleaf.fulfillment.cache.weights.all-fulfillment-calculators=0.25
broadleaf.fulfillment.cache.weights.filtered-calculators=0.25
Example Estimated Size Override (Ehcache only):
# Increase the estimated average size of a single entry in the pricing config cache
broadleaf.fulfillment.cache.sizes.fulfillment-pricing-config=10240
These overrides allow you to tune the Budget Manager’s allocation logic without changing code, ensuring that the most critical or largest caches receive appropriate memory portions.
A key feature of the Budget Manager is its Adaptive Rebalancing algorithm. This logic ensures that when you introduce new custom caches or even entire new services via a CacheManagerCustomizer, you do not necessarily need to "make room" by manually adjusting existing Broadleaf weights or budgets.
The Budget Manager performs a two-tier normalization process:
1. Service-Level Normalization (Budgets)
When multiple services (e.g., Catalog, Pricing, and your custom extensions) are running in the same JVM, each service registers its total requested heapBudget (Caffeine and Ehcache) and offHeapBudget (Ehcache only). The Budget Manager then ensures the sum of these requests never exceeds the global ceiling.
Global Summation: It sums the heapBudget and offHeapBudget from all registered services.
Global Scaling: It compares this total against the global limits (e.g., broadleaf.cache.caffeine.heap). If the sum of all service requests exceeds the global limit, the manager calculates a scale factor and scales every service’s budget down proportionally.
2. Cache-Level Normalization (Weights) Once a service’s finalized budget is determined (e.g., after being scaled by the step above), the manager performs the second tier of rebalancing for the individual caches within that service based on their weight hints.
Weight Summation: The manager sums the weight hints of all registered caches (Broadleaf defaults + your custom additions) to calculate a totalWeight.
Automatic Compression: If Broadleaf has three caches with weights 0.33, 0.33, 0.34 (total 1.0) and you add a new cache with a weight hint of 0.2, the new total becomes 1.2. Your cache will automatically receive ~16.6% (0.2 / 1.2) of the service’s memory budget, and the existing Broadleaf caches will be proportionally scaled down.
This "sum-and-scale" approach allows you to safely add new caches or services by simply providing a weight or budget that represents their relative importance. The Budget Manager ensures that the total memory footprint of the entire JVM is always respected.
Service-specific budgets like broadleaf.catalog.cache.heapBudget and broadleaf.catalog.cache.offHeapBudget do not apply to Ignite cache. heapBudget applies to both Caffeine and Ehcache. offHeapBudget only applies to Ehcache.
|
Review the following property classes for default TTL settings. You may declare properties in your own implementation config to override these values.
com.broadleafcommerce.asset.cache.AssetCacheProperties
com.broadleafcommerce.auth.cache.autoconfigure.AuthCacheProperties
com.broadleafcommerce.billing.service.cache.BillingCacheProperties
com.broadleafcommerce.cartoperation.cache.CartOperationCacheProperties
com.broadleafcommerce.catalog.cache.CatalogCacheProperties
com.broadleafcommerce.content.cache.ContentCacheProperties
com.broadleafcommerce.customer.client.autoconfigure.CustomerClientCacheProperties
com.broadleafcommerce.data.tracking.core.cache.DataTrackingCacheProperties
com.broadleafcommerce.fulfillment.cache.FulfillmentCacheProperties
com.broadleafcommerce.gateway.cache.CommerceGatewayCacheProperties
com.broadleafcommerce.menu.cache.MenuCacheProperties
com.broadleafcommerce.metadata.cache.MetadataCacheProperties
com.broadleafcommerce.notification.service.cache.NotificationCacheProperties
com.broadleafcommerce.personalization.cache.PersonalizationCacheProperties
com.broadleafcommerce.pricing.cache.PricingCacheProperties
com.broadleafcommerce.promotion.offer.cache.OfferCacheProperties
com.broadleafcommerce.search.core.cache.SearchCacheProperties
com.broadleafcommerce.search.index.core.cache.IndexCacheProperties
com.broadleafcommerce.tmforum.core.cache.autoconfigure.TMForumCoreCacheProperties
com.broadleafcommerce.translation.cache.TranslationCacheProperties
When migrating from Apache Ignite to Caffeine, you must account for several architectural changes, specifically regarding memory management and custom cache registration.
Change the property in your application configuration to point to the Caffeine implementation:
com:
broadleafcommerce:
cache:
activeCacheManagerImplementation: com.broadleafcommerce.common.extension.cache.caffeine.CaffeineAutoConfiguration
Unlike Ignite, which often used CacheManagerCustomizer<SpringCacheManager> and raw CacheConfiguration, Caffeine leverages the CaffeineBudgetManager for adaptive memory rebalancing. You must update any custom cache configurations to use this manager.
Before (Ignite):
@Bean
public CacheManagerCustomizer<SpringCacheManager> myCustomCacheCustomizer(IgniteConfigurers.BasicIgniteConfigurer configurer) {
return cacheManager -> cacheManager.getConfiguration().setCacheConfiguration(ArrayUtils.addAll(
cacheManager.getConfiguration().getCacheConfiguration(),
configurer.basicInitialize(new CacheConfiguration<>(), "my-cache", 3600)
));
}
After (Caffeine):
@Bean
public CacheManagerCustomizer<CaffeineCacheManager> myCustomCaffeineCacheCustomizer(CaffeineBudgetManager budgetManager) {
budgetManager.addCache("my-service", "my-cache", Duration.ofHours(1), 0.1);
return cacheManager -> budgetManager.addService("my-service", cacheManager, 100); // 100MB budget
}
Switching to Caffeine moves your cache on-heap. You must increase your -Xmx setting to accommodate the new heap-resident data.
Ignite: Uses off-heap native memory. Your JVM heap can be smaller, but your container limit must include the Ignite native allocation (~1GB+).
Caffeine: Uses on-heap memory. Your JVM heap must be increased by your total Caffeine budget (default 1GB).
Refer to the Memory Configuration guide for updated -Xmx and container RAM heuristics when using Caffeine.
Verify the migration by monitoring the Budget Manager’s initialization report in the application logs during startup. You should see your custom caches listed with their allocated heap sizes.
--------------------------------------------------------------------------------------------- | Service | Cache | Heap MB | --------------------------------------------------------------------------------------------- | my-service | my-cache | 90.00 | | my-service | my-cacheKeys | 10.00 | --------------------------------------------------------------------------------------------- | TOTAL | | 100.00 | ---------------------------------------------------------------------------------------------
Additionally, use the jvm_cache_* metrics in Micrometer to validate hit rates and memory consumption under load.
The easiest way to identify the relevant cache configuration for your applications, regardless of how you’ve composed your Broadleaf services, is to download the Broadleaf source code via Maven & use your IDE to search for usages of @Conditional(OnEnabledCacheCondition.class).
Each of these *AutoConfiguration classes registers the relevant cache instances. It’s worth scanning through these configurations to determine whether or not Broadleaf’s defaults meet your needs.
Overriding the default configuration is as simple as defining your own CacheManagerCustomizer bean that targets the underlying cache implementation (e.g. CaffeineCacheManager, SpringCacheManager) and replaces or supplements the relevant Broadleaf bean.
The following is an example of a client customization that adds an entirely new cache region (menu-by-location) to the existing MenuServices configuration. By using a different bean name and targeting the same SERVICE_NAME, this customizer supplements the framework defaults, and the Budget Manager automatically handles the weight rebalancing:
@Configuration
@Conditional(OnEnabledCacheCondition.class)
@ConditionalOnProperty(value = "com.broadleafcommerce.cache.activeCacheManagerImplementation",
havingValue = "com.broadleafcommerce.common.extension.cache.caffeine.CaffeineAutoConfiguration")
public class MyMenuCacheCustomization {
private static final String SERVICE_NAME = "menu";
@Bean
public CacheManagerCustomizer<CaffeineCacheManager> myMenuCacheCustomizer(CaffeineBudgetManager budgetManager) {
// Register a new custom cache region under the existing "menu" service.
// We provide a TTL of 30 minutes and a weight hint of 0.2.
budgetManager.addCache(SERVICE_NAME, "menu-by-location", Duration.ofMinutes(30), 0.2);
return cacheManager -> {}; // The Budget Manager handles the actual Caffeine initialization
}
}
In addition to being able to configure the Spring Cache, Broadleaf also allows you to configure a ModelMapper cache.
Here are a few things to understand about ModelMapper:
Broadleaf uses ModelMapper to transform data from persistence domain to projection domain.
ModelMapper (at runtime) inspects two objects that want to map data between each other and compiles the correct mapping model.
The mapping inspection takes some time the very first time it’s performed.
Mapping and caching ahead of time removes the need for the lazy cache phase at runtime.
This cuts down on the “First request after I start the service instance is slow” phenomenon.
To populate the cache, we need to exercise the persistence architecture through JPA, Hibernate, and the mapping pipeline. We simulate runtime via the Spring Boot test (i.e. StartupTest@buildModelMapperCache) and then serialize the cached state for later injection at startup during the spring boot initialization lifecycle when deployed to k8s.
The ModelMapper cache is optional. Without it, there is a possible cost of a slower first request to lazy populate the cache at production runtime. The ModelMapper cache we’re talking about here is a cache we can populate ahead of time.
ModelMapper cache is not a required concern for local development.
You can enable the ModelMapper cache via property:
broadleaf:
modelmapper:
cache:
load:
enabled: true
You will need to run and "pre-generate" the cache. You can do this via a startup test. An example startup test is available in your MicroservicesDemo accelerator project.
For example, the Balanced flex packages has the following class available:
com.broadleafdemo.demo.StartupTest#buildModelMapperCache.
you will notice that running the above test will generate the following cache artifacts in the following directory: /flexpackages/balanced/browse/src/main/resources/cache. You may sometimes need to delete/rebuild this cache if entities change/become out of date.