---
title: Configure the CMAB cache for the Flutter SDK
slug: feature-experimentation/docs/configure-the-cmab-cache-for-the-flutter-sdk-1
docTags: 
createdAt: 2026-08-05T20:39:59.000Z
---

## Prerequisites

- Flutter SDK version v3.4.0+.
- A CMAB-enabled experiment in your Optimizely Feature Experimentation 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

3.4.0

## Description

When a user is bucketed into a CMAB experiment, the Flutter 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 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, the Flutter SDK uses an in-memory Least Recently Used (LRU) 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 `CmabConfig` class.

### Default configuration

The Flutter 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.                        |
| 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.

```dart
import 'package:optimizely_flutter_sdk/optimizely_flutter_sdk.dart';

  try {
    // Initialize SDK with default CMAB configuration
    // Default cache size: 100, cache timeout: 1800 seconds (30 minutes)
    var flutterSDK = OptimizelyFlutterSdk(
      SDK_KEY,
      cmabConfig: CmabConfig(), // Uses defaults
    );

    var response = await flutterSDK.initializeClient();
    if (!response.success) {
      print('Failed to initialize SDK: ${response.reason}');
      return;
    }
    print('✓ SDK initialized successfully');

    // Create user context with attributes
    // CMAB uses these attributes to make personalized decisions
    var userContext = await flutterSDK.createUserContext(
      userId: 'user_123',
      attributes: {
        'country': 'us'
      },
    );

    if (userContext == null) {
      print('Failed to create user context');
      return;
    }
    print('✓ User context created for user_123');

    // Use decideAsync for CMAB-enabled flag
    // This makes an async call to the CMAB service for personalized variation
    // Always use ignoreUserProfileService with CMAB to get correct decisions
    print('\nMaking async decision for flag: $CMAB_FLAG_KEY');
    var decision = await userContext.decideAsync(
      CMAB_FLAG_KEY,
      {OptimizelyDecideOption.ignoreUserProfileService},
    );

  } catch (e) {
    print('Error in basicCmabExample: $e');
  }
```

## Cache 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 `ignoreCmabCache` decide option is used.
- The `invalidateUserCmabCache` decide option is used.
- The `resetCmabCache` decide option is used.

## CMAB-specific decide options

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

```dart
import 'package:optimizely_flutter_sdk/optimizely_flutter_sdk.dart';

// Ignore cache for this decision (always fetch fresh)
var decision = await userContext.decideAsync(
  CMAB_FLAG_KEY,
  {
    OptimizelyDecideOption.ignoreCmabCache
  },
);

// Invalidate cached decision for this user and experiment
var decision = await userContext.decideAsync(
  CMAB_FLAG_KEY,
  {
    OptimizelyDecideOption.invalidateUserCmabCache
  },
);

// Clear entire CMAB cache
var decision = await userContext.decideAsync(
  CMAB_FLAG_KEY,
  {
    OptimizelyDecideOption.resetCmabCache
  },
);

// Combine multiple options
var decision = await userContext.decideAsync(
  CMAB_FLAG_KEY,
  {
    OptimizelyDecideOption.resetCmabCache, OptimizelyDecideOption.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.               |
