---
title: Elixir Server SDK
description: "Statsig's Next-gen Elixir Server SDK built in our [Server Core](/server-core) framework"
product: general
token_estimate: 3938
---
# Elixir Server SDK

> For AI agents: a documentation index is available at [/llms.txt](/llms.txt). Append `.md` to any page URL for markdown, or send `Accept: text/markdown`.

- **Package:** `statsig_elixir` ([hex](https://hex.pm/packages/statsig_elixir))
- **Latest version:** 0.23.0
- **Repository:** [statsig-server-core](https://github.com/statsig-io/statsig-server-core/tree/main/statsig-elixir)

## Setup the SDK

1. **Install the SDK**

   To use the SDK, add the following to your `mix.exs`:

   ```elixir
   {:statsig_elixir, "~> 0.8.0"},
   ```

   The SDK is written using `rustler_precompiled`, which downloads a precompiled binary by default. You can also build the Rust code within your project by cloning [statsig-server-core](https://github.com/statsig-io/statsig-server-core)

   ```bash
   cd statsig-server-core/statsig-elixir/ 
   # set the environment variable 
   FORCE_STATSIG_NATIVE_BUILD="true" mix compile
   ```
2. **Initialize the SDK**

   After installation, initialize the SDK using a [Server Secret Key from the Statsig console](https://console.statsig.com/api_keys).

   > **Warning:**
   >
   > Always keep Server Secret Keys private. If you expose one, you can disable and recreate it in the Statsig console.

   An optional `options` parameter accepts a `StatsigOptions` object to customize the SDK.

   `Statsig.ex` uses GenServer to manage the Statsig instance (which is written in Rust). Add Statsig to your Supervision Tree:

   ```elixir
   # Initializing, with StatsigOptions
   sdk_key = "secret-key******" # your secret key
   statsig_options = %StatsigOptions{enable_id_lists: true}

   # Add to your supervision tree 
   statsig_spec = %{id: Statsig, start: {Statsig, :start_link, [sdk_key, statsig_options]}}
   children = [
       # Other Apps
       statsig_spec
   ]
   res = Supervisor.start_link(children, opts)

   # Or directly initialize the GenServer
   {:ok,_} = Statsig.start_link(sdk_key, statsig_options)
   Statsig.initialize()
   ```

   `initialize` performs a network request. After `initialize` completes, virtually all SDK operations are synchronous (refer to [Evaluating Feature Gates in the Statsig SDK](https://blog.statsig.com/evaluating-feature-gates-in-the-statsig-sdk-a6f8881a1ad8)). The SDK fetches updates from Statsig in the background, independent of your API calls.

## Working with the SDK

### Checking a feature flag/gate

After you initialize the SDK, you can fetch a [**Feature Gate**](https://docs.statsig.com/feature-flags/overview). Feature Gates create logic branches in code that you can roll out to different users from the Statsig Console. Gates are **CLOSED** or **OFF** (equivalent to `return false;`) by default.

All APIs require a user object (refer to [Statsig user](#statsig-user)). To check a gate for a user:

```elixir
user = %StatsigUser{
    user_id: "test_user_123"
}

{:ok, check_gate} = Statsig.check_gate("test_public", user)
# check_gate will be a boolean
```

### Reading a dynamic config

Feature Gates are useful for simple on/off switches with optional user targeting. To send different values (strings, numbers, etc.) to clients based on user attributes such as country, use [**Dynamic Configs**](https://docs.statsig.com/dynamic-config/overview). The API is similar to Feature Gates, but returns a JSON object from which you can retrieve typed parameters. For example:

```elixir
# Get a dynamic config for a specific user
user = %StatsigUser{
    user_id: "test_user_123"
}
{:ok, config} = Statsig.get_dynamic_config("a_config", user)

# Access the values in the dynamic config:

param_value = DynamicConfig.get_param_value(config, "header_text")

# Disable exposure
options = %Statsig.DynamicConfigEvaluationOptions{
    disable_exposure_logging = true
}
{:ok, config} = Statsig.get_dynamic_config("a_config", user, options)

```

### Getting a layer/experiment

**Layers/Experiments** let you run A/B/n experiments. Two APIs are available, but Statsig recommends [layers](https://docs.statsig.com/experiments/layers-overview) because layers make parameters reusable and support mutually exclusive experiments.

```elixir
# Values via get_layer
user = %StatsigUser{
    user_id: "test_user_123"
}

{:ok, layer} = Statsig.get_layer("user_promo_experiments", user)
{:ok, title_string_value} = Layer.get(layer, "title", "Welcome to Statsig!")
{:ok, discount_float_value} = Layer.get(layer, "discount", 0.1)

# Via get_experiment
{:ok, experiment} = Statsig.get_experiment("user_promo_experiment", user)
title_exp = Experiment.get_param_value(experiment, "new_user_promo_title")

# Disable exposure
options = %Statsig.ExperimentEvaluationOptions{
    disable_exposure_logging = true
}
{:ok, experiment} = Statsig.get_experiment("user_promo_experiment", user, options)
```

> **Note:**
>
> When you use a layer to get a value, use get param value. This method returns primitive types (boolean, string, and numbers). For more complex types, the SDK returns JSON-serialized values.

### Retrieving feature gate metadata

To retrieve more information about a gate evaluation than a boolean value, use the Get Feature Gate API, which returns a `FeatureGate` object:

```elixir
{:ok, feature_gate} = Statsig.get_feature_gate(user, "example_gate")
# access the value, or the name off of the feature_gate object

options = %Statsig.FeatureGateEvaluationOptions{
    disable_exposure_logging = true
}
{:ok, feature_gate} = Statsig.get_feature_gate(user, "example_gate", options)

```

### Parameter stores

If you want dynamic control over whether a value comes from a Feature Gate, Experiment, or Dynamic Config outside your deployment cycle, use Parameter Stores. A Parameter Store lets you define a parameter that you can change at any point in the Statsig console. Parameter Stores are optional, but parameterizing your application supports future flexibility and allows non-technical Statsig users to turn parameters into experiments.

> **Note:**
>
> _Parameter stores are not yet available for this sdk. Need it now? Reach out in Slack._

### Logging an event

After setting up a Feature Gate or Experiment, track custom events to measure how features or experiment groups affect user behavior. Call the Log Event API and specify the user and event name. You can also provide a value and metadata:

```elixir
Statsig.log_event(user, "test_event", 1, %{"metadata_1" => "value"})
```

### Sending events to Log Explorer

You can forward logs to Logs Explorer for analysis using the Forward Log Line Event API. The API lets you include custom metadata and event values with each log.

> **Note:**
>
> Sending events to Log Explorer is not yet available for this sdk. Need it now? Reach out in Slack.

## Statsig user

The `StatsigUser` object represents a user in Statsig. You must provide a `userID` or at least one of the `customIDs` to identify the user.

When calling APIs that require a user, pass as much information as possible. More user attributes enable advanced gate and config conditions (such as country or OS/browser checks) and more accurate experiment impact measurement. You must provide at least one identifier (userID or customID) to ensure a consistent experience for a given user. For details, refer to [why an ID is always required for server SDKs](https://docs.statsig.com/sdks/user#why-is-an-id-always-required-for-server-sdks).

In addition to `userID`, the top-level fields on `StatsigUser` are: `email`, `ip`, `userAgent`, `country`, `locale`, and `appVersion`. You can also pass key-value pairs in the `custom` field for targeting.

### Private attributes

Private attributes are user attributes that Statsig uses for evaluation but doesn't forward to any integrations. Use them for PII or sensitive data that you don't want to send to third-party services.

```elixir
user = %Statsig.User{
  user_id: "a-user-id",
  email: "user@example.com",
  ip: "192.168.1.1",
  user_agent: "Mozilla/5.0...",
  country: "US",
  locale: "en_US",
  app_version: "1.0.0",
  custom: %{
    # Custom fields
    "plan" => "premium",
    "age" => 25
  },
  custom_ids: %{
    # Custom ID types
    "stable_id" => "stable-id-123"
  },
  private_attributes: %{
    # Private attributes not forwarded to integrations
    "email" => "private@example.com"
  }
}
```

## Statsig options

You can pass an optional `options` parameter in addition to `sdkKey` during initialization to customize the Statsig client.

#### StatsigOptions

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| environment | string | No | — | The environment you're operating in (e.g., Production) |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| output_log_level | string | No | — | The type of logs you'd like exposed. (e.g., Debug) |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| init_timeout_ms | number | No | — | How long it should take for initialization to time out. |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| event_logging_flush_interval_ms | number | No | — | How often events should flush to the Statsig servers. |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| event_logging_max_queue_size | Option<u32> | No | — | Maximum number of events to queue before forcing a flush.- Default is `2000` - event\_logging\_max\_queue\_size \* event\_logging\_max\_pending\_batch\_queue\_size is the upper limit on how many events are queued - See also `event_logging_max_pending_batch_queue_size` |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| event_logging_max_pending_batch_queue_size | Option<u32> | No | — | Maximum number of event batches to hold in buffer to retry.- Default is `100`. - event\_logging\_max\_queue\_size \* event\_logging\_max\_pending\_batch\_queue\_size is the upper limit on how many events are queued - eg: 2000 \* 100 means the SDK can process 200k event per second before events start getting dropped - See also `event_logging_max_queue_size`. |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| log_event_url | string | No | — | The URL events should be logged to |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| specs_sync_interval_ms | number | No | — | How often specs should sync from the Statsig servers |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| specs_url | string | No | — | The URL Statsig should download specs from |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| spec_adapter_configs | list | No | — | Advanced configuration for fetching specs from custom sources, including [Statsig Forward Proxy](https://docs.statsig.com/infrastructure/api_proxy/introduction). |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| enable_id_lists | boolean | No | — | Enable ID list download. **Required to be `true` when using segments with more than 1000 IDs.** See [ID List segments](https://docs.statsig.com/segments/add-id-list) for more details. |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| id_lists_url | string | No | — | The URL ID lists should be downloaded from |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| id_lists_sync_interval_ms | number | No | — | How often ID lists should be synced. |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| wait_for_country_lookup_init | boolean | No | — | Block initialization call until country lookup is initialized |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| wait_for_user_agent_init | boolean | No | — | Block initialization call until user\_agent is initialized |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| disable_all_logging | boolean | No | — | When `true`, disables all event logging. |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| disable_country_lookup | boolean | No | — | To improve memory usage, disable using country lookup. |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| disable_network | boolean | No | — | Turn off all network requests including get\_dcs and log\_events |

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| disable_user_agent_parsing | boolean | No | — | To improve memory usage, disable using user agent parsing. |

---

```elixir
# Initialize StatsigOptions with custom parameters
statsig_options = %StatsigOptions{
  enable_id_lists: true
}

# Pass the options object into statsig.initialize()
{:ok, _} = Statsig.start_link(sdk_key, statsig_options)
Statsig.initialize()
```

### Proxy and custom network routing

The Elixir Server Core SDK doesn't document a dedicated outbound HTTP proxy config. For custom network routing, use `spec_adapter_configs` for [Statsig Forward Proxy](https://docs.statsig.com/infrastructure/api_proxy/introduction) or set `specs_url`, `log_event_url`, and `id_lists_url` directly.

```elixir
statsig_options = %StatsigOptions{
  spec_adapter_configs: [
    %Statsig.SpecAdapterConfig{
      adapter_type: "network_grpc_websocket",
      specs_url: "http://forward-proxy.internal:50051",
      authentication_mode: "none"
    }
  ],
  fallback_to_statsig_api: true
}
```

## Shutting Statsig down

Because the SDK batches events and periodically flushes them, some events might not send before your app or server shuts down. To flush all logged events, call `shutdown()` before your app or server shuts down:

```elixir
Statsig.shutdown()
```

## Client SDK Bootstrapping | SSR

If you are using the Statsig client SDK in a browser or mobile app, you can bootstrap the client SDK with values from the server SDK to avoid a network request on the client. Bootstrapping is useful for server-side rendering (SSR) or when you want to reduce the number of network requests on the client.

```elixir
# Get client initialize response for a user
{:ok, response} = Statsig.get_client_init_response_as_string(user)

# Pass values to a client SDK to initialize without a network request
```

## Persistent storage

The Persistent Storage interface lets you implement custom storage for user-specific configurations. Use it to persist user assignments across sessions, ensuring consistent experiment groups when users return. Persistent storage is useful for client-side A/B testing where users must always see the same variant.

> **Note:**
>
> Not supported yet.

## Data store

The Data Store interface lets you implement custom storage for Statsig configurations, enabling advanced caching strategies and integration with your preferred storage systems.

> **Note:**
>
> Not supported yet.

## Custom output logger

The Output Logger interface lets you customize how the SDK logs messages, enabling integration with your own logging system and control over log verbosity.

> **Note:**
>
> Not supported yet.

## Observability client

The Observability Client interface lets you monitor SDK health by integrating with your own observability systems, enabling tracking of metrics, errors, and performance data. For more information on the metrics emitted by Statsig SDKs, go to the [Monitoring documentation](https://docs.statsig.com/infrastructure/sdk-monitoring).

> **Note:**
>
> Not supported yet.

## FAQ

#### How do I run experiments for logged out users?

Refer to the guide on [device level experiments](https://docs.statsig.com/guides/logging-events#device-level-events)

