Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

Dev guideRecipesAPI ReferenceChangelog
Dev guideAPI ReferenceRecipesChangelogUser GuideGitHubDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Configure the CMAB cache for Agent

Configure caching behavior for Contextual Multi-Armed Bandit (CMAB) decisions in Optimizely Agent.

👍

Beta

CMAB for Feature Experimentation is in beta. Contact your Customer Success Manager for more information.

The CMAB cache for Optimizely Agent stores variation assignments to reduce latency and minimize API calls to the CMAB service.

Prerequisites

  • Optimizely Agent version 4.3.0 or higher.
  • A CMAB-enabled experiment in your Optimizely Feature Experimentation project.

Description

When a user is bucketed into a CMAB experiment, Optimizely Agent makes an API call to the CMAB service to determine which variation to display. To improve performance and reduce latency, Optimizely Agent caches these decisions based on the following:

  • 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, Optimizely Agent uses an in-memory least recently sed (LRU) cache with a size of 10,000 entries and a timeout of 30 minutes. You can customize these settings in your config.yaml configuration file, or configure Redis for shared caching across multiple Optimizely Agent instances.

Parameters

Configure CMAB caching in your config.yaml file under the client.cmab section.

Configuration structure

client:
  cmab:
    requestTimeout: 10s
    ## URL template for CMAB prediction API with %s placeholder for experimentId
    predictionEndpoint: "https://prediction.cmab.optimizely.com/predict/%s"
    cache:
      default: "in-memory"
      services:
        in-memory:
          size: 10000
          timeout: 30m
        redis:
          host: "localhost:6379"
          password: ""
          database: 0
          timeout: 30m
    retryConfig:
      maxRetries: 1
      initialBackoff: 100ms
      maxBackoff: 10s
      backoffMultiplier: 2.0

Top-level CMAB parameters

Configure the following parameters in client.cmab:

ParameterTypeRequiredDefaultDescription
requestTimeoutdurationNo10sTimeout for CMAB API requests. Increase for slower network connections.
predictionEndpointstringNohttps://prediction.cmab.optimizely.com/predict/%sURL template for CMAB prediction service. Override for testing or staging environments.

Cache parameters

Configure the following cache behavior in client.cmab.cache:

ParameterTypeRequiredDefaultDescription
defaultstringNo"in-memory"Default cache service to use. Options include "in-memory" or "redis".

In-memory service parameters

Configure in-memory cache in client.cmab.cache.services.in-memory with the following parameters:

ParameterTypeRequiredDefaultDescription
sizeintNo10000Maximum number of decisions to cache. Increase for applications with many users or experiments.
timeoutdurationNo30mHow long cache entries remain valid. Lower values ensure fresher decisions but increase API calls.

Redis service parameters

Configure the Redis cache in client.cmab.cache.services.redis with the following parameters:

ParameterTypeRequiredDefaultDescription
hoststringYes-Redis server address. For example "localhost:6379".
passwordstringNo""Redis password for authentication.
databaseintNo0Redis database number to use.
timeoutdurationNo30mHow long cache entries remain valid.

Retry parameters

Configure the exponential backoff retry behavior in client.cmab.retryConfig with the following parameters:

ParameterTypeRequiredDefaultDescription
maxRetriesintNo1Maximum number of retry attempts for failed CMAB API requests. 1 means up to two total attempts. One initial + one retry.
initialBackoffdurationNo100msInitial wait time before first retry.
maxBackoffdurationNo10sMaximum wait time between retries.
backoffMultiplierfloat64No2.0Multiplier for exponential backoff (each retry waits longer).
📘

Note

Duration values can be specified in seconds (for example "5s"), minutes (for example, "30m"), or milliseconds (for example, "500ms").

Examples

Basic configuration

Adjust the cache size and timeout for your application's needs.

# config.yaml
client:
  cmab:
    # Allow 15 seconds for CMAB API calls
    requestTimeout: 15s
    predictionEndpoint: "https://prediction.cmab.optimizely.com/predict/%s"

    cache:
      default: "in-memory"
      services:
        in-memory:
          # Cache up to 5000 decisions
          size: 5000
          # Refresh cache every 10 minutes
          timeout: 10m

High-traffic configuration

For applications with many users and CMAB experiments.

# config.yaml
client:
  cmab:
    requestTimeout: 10s
    predictionEndpoint: "https://prediction.cmab.optimizely.com/predict/%s"

    cache:
      default: "in-memory"
      services:
        in-memory:
          # Increase cache size for more users
          size: 20000
          # Keep decisions cached for 1 hour
          timeout: 1h

    retryConfig:
      # Retry up to 5 times for resilience
      maxRetries: 5
      initialBackoff: 200ms
      maxBackoff: 30s
      backoffMultiplier: 2.0

Low-latency configuration

For applications requiring frequently updated decisions.

# config.yaml
client:
  cmab:
    # Shorter timeout for faster failures
    requestTimeout: 5s
    predictionEndpoint: "https://prediction.cmab.optimizely.com/predict/%s"

    cache:
      default: "in-memory"
      services:
        in-memory:
          size: 10000
          # Refresh decisions every 5 minutes
          timeout: 5m

    retryConfig:
      # Fewer retries for faster responses
      maxRetries: 0
      initialBackoff: 50ms
      maxBackoff: 5s
      backoffMultiplier: 2.0

Redis configuration

For multi-instance deployments with shared caching.

# config.yaml
client:
  cmab:
    requestTimeout: 10s
    predictionEndpoint: "https://prediction.cmab.optimizely.com/predict/%s"

    cache:
      default: "redis"
      services:
        redis:
          host: "localhost:6379"
          password: ""
          database: 0
          # Keep decisions cached for 30 minutes
          timeout: 30m

Making decide requests

After Optimizely Agent is configured, use the /v1/decide endpoint to get CMAB decisions.

curl -X POST https://your-agent-host:8080/v1/decide \
  -H "X-Optimizely-SDK-Key: your-sdk-key" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "userAttributes": {
      "age": 25,
      "location": "US"
    },
    "decideOptions": ["INCLUDE_REASONS"],
    "decisionContext": {
      "flagKey": "my-cmab-flag"
    }
  }'

Response.

{
  "userId": "user123",
  "flagKey": "my-cmab-flag",
  "enabled": true,
  "variationKey": "variation_a",
  "ruleKey": "cmab-rule-1",
  "reasons": [
    "Returning cached CMAB decision",
    "User \"user123\" bucketed into variation \"variation_a\" by CMAB service"
  ],
  "variables": {
    "color": "blue",
    "size": "large"
  }
}

Cache behavior

Cache invalidation

The cache is automatically invalidated when

  • The cached entry's timeout period expires.
  • CMAB attribute values change for a user (detected through attribute hash comparison).
  • The /v1/reset endpoint is called (for testing).

Decide options

Control decision behavior using decideOptions in your /v1/decide request.

curl -X POST https://your-agent-host:8080/v1/decide \
  -H "X-Optimizely-SDK-Key: YOUR_SDK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "decideOptions": ["INCLUDE_REASONS", "EXCLUDE_VARIABLES"],
    "decisionContext": {
      "flagKey": "my-cmab-flag"
    }
  }'

Available options

  • DISABLE_DECISION_EVENT – Skip sending impression events for this decision.
  • INCLUDE_REASONS – Include detailed reasoning for the decision in the response.
  • EXCLUDE_VARIABLES – Exclude variable values from the response.
  • ENABLED_FLAGS_ONLY – Only return decisions for enabled flags.
  • IGNORE_USER_PROFILE_SERVICE – Skip user profile service lookup for this decision.
  • IGNORE_CMAB_CACHE – Bypass CMAB cache and fetch a fresh decision from CMAB service.
  • INVALIDATE_USER_CMAB_CACHE – Invalidate cached CMAB decisions for this user and experiment before deciding.
  • RESET_CMAB_CACHE – Clear all CMAB cache entries before deciding (affects all users).

CMAB-specific decide options

The following decide options control CMAB cache behavior:

IGNORE_CMAB_CACHE

Use this option to bypass the cache and always fetch a fresh decision from the CMAB service.

Use case – One-off requests where you need the absolute freshest decision from the CMAB service.

Example scenario

# VIP user - always get fresh CMAB decision, never use cache.
curl -X POST https://your-agent-host:8080/v1/decide \
  -H "X-Optimizely-SDK-Key: YOUR_SDK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "vip_user_456",
    "userAttributes": {
      "tier": "platinum"
    },
    "decideOptions": ["IGNORE_CMAB_CACHE"],
    "decisionContext": {
      "flagKey": "my-cmab-flag"
    }
  }'

INVALIDATE_USER_CMAB_CACHE

Use this option to invalidate cached CMAB decisions for this specific user and experiment before making a new decision.

Use case – When you know the user's context has changed but the attributes in your current request don't reflect it yet.

Example scenario

# User just made a purchase. Their behavior profile changed.
# But we are sending same attributes. We want fresh CMAB decision.
curl -X POST https://your-agent-host:8080/v1/decide \
  -H "X-Optimizely-SDK-Key: YOUR_SDK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "userAttributes": {
      "country": "us",
      "age": 25
    },
    "decideOptions": ["INVALIDATE_USER_CMAB_CACHE"],
    "decisionContext": {
      "flagKey": "my-cmab-flag"
    }
  }'

RESET_CMAB_CACHE

Use this option to clear the entire CMAB cache (all users and all experiments) before making a decision.

Use case – Clear entire CMAB cache when you need to ensure all users get fresh decisions.

Example scenario

# CMAB model was just retrained. Clear all cached decisions.
curl -X POST https://your-agent-host:8080/v1/decide \
  -H "X-Optimizely-SDK-Key: YOUR_SDK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "any_user",
    "decideOptions": ["RESET_CMAB_CACHE"],
    "decisionContext": {
      "flagKey": "my-cmab-flag"
    }
  }'
❗️

Warning

RESET_CMAB_CACHE affects all users and should be used sparingly, typically only in testing or when CMAB models are updated.

Decision reasons

When you include "INCLUDE_REASONS" in your decide options, Optimizely Agent provides detailed reasons that help you understand how the decision was made, including cache behavior.

Example request with reasons

curl -X POST https://your-agent-host:8080/v1/decide \
  -H "X-Optimizely-SDK-Key: YOUR_SDK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "userAttributes": {
      "age": 25
    },
    "decideOptions": ["INCLUDE_REASONS"],
    "decisionContext": {
      "flagKey": "my-cmab-flag"
    }
  }'

Example response with reasons

{
  "userId": "user123",
  "flagKey": "my-cmab-flag",
  "enabled": true,
  "variationKey": "variation_a",
  "reasons": [
    "Returning cached CMAB decision",
    "User \"user123\" bucketed into variation \"variation_a\" by CMAB service"
  ]
}

The reasons array includes the following information:

  • Whether the decision was served from cache or fetched from the CMAB service.
  • Cache invalidation events.
  • Bucketing results.
  • Any errors encountered during decision-making.

Reset endpoint

Agent provides a /v1/reset endpoint to clear the client cache, including CMAB decisions. This is primarily used for testing.

Request

curl -X POST https://your-agent-host:8080/v1/reset \
  -H "X-Optimizely-SDK-Key: your-sdk-key"

Response

{
  "result": true
}
🚧

Important

The reset endpoint clears the entire client cache for the specified SDK key, including the following:

  • CMAB cache.
  • Datafile cache.
  • All other cached data.

This ensures a clean state for testing but should not be used in production.

Custom CMAB endpoint

For testing or staging environments, you can override the default CMAB prediction endpoint (https://prediction.cmab.optimizely.com/predict/%s).

With config.yaml

# config.yaml
client:
  cmab:
    predictionEndpoint: "https://staging-cmab.example.com/predict/%s"

With an environment variable

export OPTIMIZELY_CMAB_PREDICTIONENDPOINT="https://staging-cmab.example.com/predict/%s"
📘

Note

Environment variable takes priority over the config.yaml setting.

Multi-instance deployments

In-memory cache

The in-memory cache is isolated to each Agent instance and cannot be shared. For multi-instance deployments, consider using Redis for shared caching.

Redis cache

Agent supports Redis for shared caching across multiple instances. Configure Redis in your config.yaml file.

# config.yaml
client:
  cmab:
    predictionEndpoint: "https://prediction.cmab.optimizely.com/predict/%s"
    cache:
      default: "redis"
      services:
        redis:
          host: "localhost:6379"
          password: ""
          database: 0
          timeout: 30m

Redis availability

If Redis becomes unavailable

  • New decisions fall back to CMAB API calls (no caching).
  • Existing cached entries become inaccessible.
  • Agent continues serving decisions (degraded performance).