Configure the CMAB cache for the Python SDK
Configure caching behavior for Contextual Multi-Armed Bandit (CMAB) decisions in the Feature Experimentation Python SDK.
BetaCMAB for Feature Experimentation is in beta. Contact your Customer Success Manager for more information.
The CMAB cache stores variation assignments to reduce latency and minimize API calls to the CMAB service.
Prerequisites
- Python SDK version 5.3.0 or higher.
- A CMAB-enabled experiment in your Optimizely Feature Experimentation project.
Minimum SDK version
5.3.0
Description
When a user is bucketed into a CMAB experiment, the SDK makes an API call to the CMAB service to determine which variation to display. To improve performance and reduce latency, the SDK caches these decisions based on:
- User ID.
- Experiment ID.
- CMAB attribute values.
The cache is automatically invalidated when CMAB attributes change for a user, ensuring fresh decisions when context changes.
By default, the SDK uses an in-memory Least Recently Used (LRU) cache with a maximum size of 10000 entries and a TTL of 30 minutes (1800 seconds). You can customize these settings or provide your own cache implementation.
Configuration options
Configure CMAB caching using the OptimizelyFactory class methods before creating your Optimizely client instance.
Default configuration
The SDK uses these default values when no custom configuration is provided:
Setting | Default Value | Description |
|---|---|---|
Cache Implementation |
| Thread-safe in-memory LRU cache. |
Cache Size |
| Maximum number of cached decisions. |
Cache TTL |
| Time-to-live for cache entries. |
cmab_prediction_endpoint |
| URL template for CMAB
prediction API. The |
Configuration methods
Set cache size
OptimizelyFactory.set_cmab_cache_size(cache_size, logger=None)Parameters
cache_size(int) – Maximum number of decisions to cache. Must be a positive integer.- (Optional)
logger– Logger for logging validation errors.
Example
from optimizely.optimizely_factory import OptimizelyFactory
from optimizely import logger as optimizely_logger
logger = optimizely_logger.SimpleLogger()
# Set cache size to 500 entries
OptimizelyFactory.set_cmab_cache_size(500, logger)Set cache TTL
OptimizelyFactory.set_cmab_cache_ttl(cache_ttl, logger=None)Parameters:
cache_ttl(int): Time in seconds for cache entries to live. Must be a positive number.- (Optional)
logger– Logger for logging validation errors.
Example
from optimizely.optimizely_factory import OptimizelyFactory
from optimizely import logger as optimizely_logger
logger = optimizely_logger.SimpleLogger()
# Set cache TTL to 10 minutes (600 seconds)
OptimizelyFactory.set_cmab_cache_ttl(600, logger)Set custom cache
OptimizelyFactory.set_cmab_custom_cache(custom_cache)Parameters
custom_cache– Custom cache implementation that responds tolookup,save,remove, andresetmethods.
Example
# Provide your own cache implementation
OptimizelyFactory.set_cmab_custom_cache(my_custom_cache)Examples
Basic configuration
Adjust cache size and TTL for your application's needs, like in the following example:
from optimizely.optimizely_factory import OptimizelyFactory
from optimizely import logger as optimizely_logger
logger = optimizely_logger.SimpleLogger()
# Configure CMAB cache settings.
OptimizelyFactory.set_cmab_cache_size(500, logger) # Cache up to 500 decisions
OptimizelyFactory.set_cmab_cache_ttl(600, logger) # Refresh cache every 10 minutes
# Create Optimizely client
optimizely_client = OptimizelyFactory.custom_instance(
'YOUR_SDK_KEY',
None, # datafile (optional)
None, # event_dispatcher (optional)
logger # logger
)
# Use the client normally
user = optimizely_client.create_user_context('user123', {
'age': 25,
'location': 'US'
})
decision = user.decide('my-cmab-flag')
# Cache storeS this decision for 10 minutes.Advanced: Custom cache implementation
For multi-instance deployments or distributed systems, you can provide your own cache implementation, like in the following example:
from optimizely.optimizely_factory import OptimizelyFactory
from optimizely import logger as optimizely_logger
# Example: Custom cache implementation for distributed systems.
# You can use Redis, Memcached, or any other caching system.
class CustomCmabCache:
def __init__(self):
# Initialize your cache backend here.
# For example: self.redis = Redis(), self.memcached = Client(), and so on.
pass
def lookup(self, key):
# Retrieve value from your cache backend.
# Return the cached value if found, None otherwise.
# Example: return self.redis.get(key)
pass
def save(self, key, value):
# Store the key-value pair in your cache backend.
# Consider setting an expiration/TTL if your backend supports it.
# Example: self.redis.setex(key, ttl, value)
pass
def remove(self, key):
# Remove the key from your cache backend.
# Example: self.redis.delete(key)
pass
def reset(self):
# Clear all CMAB cache entries from your cache backend.
# Example: self.redis.flushdb() or clear specific key patterns
pass
# Create and configure your custom cache.
custom_cache = CustomCmabCache()
# Configure Optimizely with custom cache.
OptimizelyFactory.set_cmab_custom_cache(custom_cache)
# Create Optimizely client
optimizely_client = OptimizelyFactory.custom_instance(
'YOUR_SDK_KEY',
None,
None,
optimizely_logger.SimpleLogger()
)
# CMAB decisions now use your custom cache
user = optimizely_client.create_user_context('user123', {
'device_type': 'mobile'
})
decision = user.decide('my-cmab-flag')Custom cache interface
To implement a custom cache, your cache must implement the following four methods:
class CustomCmabCache:
# Retrieve a value from the cache.
# @param key [str] The cache key
# @return [dict, None] The cached value if found, None otherwise
def lookup(self, key):
# Your implementation here
pass
# Store a key-value pair in the cache.
# @param key [str] The cache key
# @param value [dict] The value to cache
def save(self, key, value):
# Your implementation here
pass
# Remove a key from the cache.
# @param key [str] The cache key to remove
def remove(self, key):
# Your implementation here
pass
# Clear all entries from the cache.
def reset(self):
# Your implementation here
passCache behavior
Automatic cache invalidation
The cache is automatically invalidated when
- The cached entry's TTL expires.
- CMAB attribute values change for a user (detected through MD5 hash comparison).
- The
IGNORE_CMAB_CACHEdecide option is used. - The
INVALIDATE_USER_CMAB_CACHEdecide option is used. - The
RESET_CMAB_CACHEdecide option is used.
CMAB-specific decide options
Control cache behavior on a per-decision basis using decide options, like in the following example:
from optimizely.decision.optimizely_decide_option import OptimizelyDecideOption
# Ignore cache for this decision (always fetch fresh).
decision = user.decide('my-flag', [
OptimizelyDecideOption.IGNORE_CMAB_CACHE
])
# Invalidate cached decision for this user and experiment.
decision = user.decide('my-flag', [
OptimizelyDecideOption.INVALIDATE_USER_CMAB_CACHE
])
# Clear entire CMAB cache.
decision = user.decide('my-flag', [
OptimizelyDecideOption.RESET_CMAB_CACHE
])
# Combine multiple options.
decision = user.decide('my-flag', [
OptimizelyDecideOption.INCLUDE_REASONS,
OptimizelyDecideOption.IGNORE_CMAB_CACHE
])Available CMAB decide options
The following are the available decide options with a short description of what they do:
IGNORE_CMAB_CACHE– Bypass cache and fetch a fresh decision from CMAB service.INVALIDATE_USER_CMAB_CACHE– Remove cached decision for this user and experiment before deciding.RESET_CMAB_CACHE– Clear all entries from the CMAB cache before deciding.
When to use a custom cache
Consider implementing a custom cache in the following scenarios:
- Multi-instance deployments – Share cache across multiple application instances using Redis, Memcached, or similar.
- Distributed systems – Use external caching systems for centralized caching across services.
- Persistent cache – Maintain cache across application restarts.
- Custom eviction policies – Implement domain-specific cache management (for example, user-based eviction).
- Monitoring – Track cache metrics (hit rate, memory usage, and so on) with your existing monitoring tools.
- Compliance – Store cached data in specific locations or with specific encryption requirements.
Updated about 1 hour ago