---
title: Configure the CMAB cache for the Swift SDK
slug: feature-experimentation/docs/cmab-cache-config-for-the-swift-sdk
docTags: 
createdAt: 2026-08-05T20:40:03.000Z
---

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

## Prerequisites

- Swift SDK version v5.2.0+
- A CMAB-enabled experiment in your Optimizely project

:::hint{type="warning"}
**Important**

To retrieve a CMAB decision, you must use the `decideAsync` method. The `decide` method does not fetch CMAB decisions to avoid blocking the user.
:::

## Minimum SDK version

5.2.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 show. 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 LRU (Least Recently Used) cache with a maximum size of 100 entries and a TTL of 30 minutes (1800 seconds). You can customize these settings.

## Configuration options

Configure CMAB caching when initializing your client using a `CmabConfig` struct.

### Default configuration

The Swift SDK uses the following default values when no custom configuration is provided:

| Setting              | Default Value                                       | Description                                                                     |
| -------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------- |
| Cache Size           | `100`                                               | Maximum number of cached decisions.                                             |
| Cache TTL            | `1800` seconds (30 minutes)                         | Time-to-live for cache entries.                                                 |
| Prediction Endpoint  | `https://prediction.cmab.optimizely.com/predict/%@` | The `%@` placeholder is replaced with the rule ID. This is useful for proxying. |
| Cache Implementation | `LruCache`                                          | Thread-safe in-memory Least Recently Used (LRU) cache.                          |

## Examples

### Basic configuration

Adjust cache size and TTL for your application's needs.

```swift
import Foundation
import Optimizely
import UIKit


// Configure CMAB settings
let cmabConfig = CmabConfig(
    cacheSize: 10,
    cacheTimeoutInSecs: 600
)

// Initialize client with custom cmab config
let client = OptimizelyClient(
    sdkKey: "<your_sdk_key>",
    cmabConfig: cmabConfig
)

Task {
    try await client.start()
    let user = OptimizelyUserContext(
        optimizely: client,
        userId: "USER_123",
        attributes: ["country": "us"]
    )
    let decision =  await user.decideAsync(key: "cmab_flag_key")
    // Cache will store this decision for 10 minutes
}
```

## Cache behavior

### Automatic cache invalidation

The cache is automatically invalidated when:

- The cached entry's TTL expires.
- CMAB attribute values change for a user. The SDK detects the change by comparing MurmurHash3 hashes of the attributes.
- The `invalidateUserCmabCache` decide option is used.
- The `resetCmabCache` decide option is used.

The `ignoreCmabCache` decide option bypasses the cache for that call without modifying cached entries.

## CMAB-Specific decide options

Control cache behavior on a per-decision basis using decide options.

```swift
import Foundation
import Optimizely
import UIKit

// Ignore cache for this decision (always fetch fresh)
let decision =  await user.decideAsync(key: "cmab_flag_key", options: [.ignoreCmabCache])

// Invalidate cached decision for this user and experiment
let decision =  await user.decideAsync(key: "cmab_flag_key", options: [.invalidateUserCmabCache])

// Clear entire CMAB cache
let decision =  await user.decideAsync(key: "cmab_flag_key", options: [.resetCmabCache])

// Combine multiple options
let decision =  await user.decideAsync(key: "cmab_flag_key", options: [.resetCmabCache, .includeReasons])
```

### Available CMAB decide options

| Decide option             | Description                                                          |
| ------------------------- | -------------------------------------------------------------------- |
| `ignoreCmabCache`         | Bypass cache and fetch a fresh decision from CMAB service.           |
| `invalidateUserCmabCache` | Remove cached decision for this user and experiment before deciding. |
| `resetCmabCache`          | Clear all entries from the CMAB cache before deciding.               |
