# Local Eval Adapter

## Local Eval Adapter

A common limitation of experimentation systems is the **dependence on an upfront network request to fetch experiment configurations**. [Bootstrapping](https://docs.statsig.com/client/concepts/initialize#2-bootstrap-initialization) and [Synchronous Initialization](https://docs.statsig.com/client/concepts/initialize#4-synchronous-initialization) offer alternatives, but both have limitations. Bootstrapping still requires an upfront request, though you can make it synchronous with other requests. Synchronous initialization can result in configs that are out of date by one session.

The Local Eval Adapter removes this dependence by letting you ship experiment configurations inline with your application, so you can run experiments before initialization completes. The adapter expects a ruleset defining your experiments, similar to Statsig's Server SDKs. Refer to the [Example Ruleset below](#example-ruleset-config-spec).

## Limitations

Shipping with a ruleset presents security concerns. When you scope the experiment set to only a few experiments that run before any network requests, those concerns are often minimal. Exercise caution when shipping a ruleset in production code and verify that the contents are correct and safe.

## Usage & functionality

With proper attention to security and maintenance of the ruleset in your application, the Local Eval Adapter addresses the downsides of other experiment-at-launch strategies.

{% callout type="info" %}
The local evaluation adapter is for Enterprise and Pro Tier companies only. If you're trying to follow these instructions but don't meet that criteria, some of the setup steps may not work.
{% /callout %}

The Adapter manifests as a StatsigOptions object seeded with a ruleset payload:

{% tabs %}
{% tab title="iOS" %}
```swift
    Statsig.initialize(
        sdkKey: "client-sdkkey",
        user: user,
        options: StatsigOptions(
            overrideAdapter: OnDeviceEvalAdapter(stringPayload: onDeviceEvalAdapterRulesetPayload)
        )
    ) { err in
        // Initialization completed. `err` is `nil` if it was successful
    }
```
{% /tab %}

{% tab title="Android" %}
```kotlin
    val adapter = OnDeviceEvalAdapter("...") // dcs payload as string
    val user = StatsigUser("a-user")
    
    Statsig.initializeAsync(application, "client-sdk", user, object : IStatsigCallback {
      override fun onStatsigInitialize() {
        println(adapter.getGate(Statsig.getFeatureGate("a_gate"), user)?.details?.reason) // [OnDevice] Bootstrap:Recognized
        println(Statsig.getFeatureGate("a_gate").details.reason) // Network:Recognized
      }
    })
```
{% /tab %}

{% tab title="JavaScript" %}
```js
    const adapter = new OnDeviceEvalAdapter();
    adapter.setData('...'); // dcs payload as string

    const client = new StatsigClient(
      'client-...',
      { userID: 'a-user' },
      {
        overrideAdapter: adapter,
      },
    );

    // purposely not awaiting this, will use local specs until network is resolved
    const isReady = client.initializeAsync();

    const localEvalGate = client.getFeatureGate('a_gate');
    console.log(localEvalGate.details.reason); // [OnDevice] Bootstrap:Recognized

    await isReady;

    const networkEvalGate = client.getFeatureGate('a_gate');
    console.log(networkEvalGate.details.reason); // Network:Recognized
```
{% /tab %}
{% /tabs %}

### Example ruleset "Config Spec"

The ruleset is a JSON object that contains the following fields:

```json
{
  "feature_gates": [],
  "dynamic_configs": [],
  "layer_configs": [],
  "time": 1735718400000
}
```

You can retrieve your ruleset by API. Use target apps to scope the ruleset to only the experiments and feature gates needed on startup. For assistance, reach out in your Slack channel or the [community Slack](https://statsig.com/slack).
