# Initializing SDKs

The first step in using a Statsig SDK is calling `initialize()`, which retrieves the values needed to evaluate experiments and send events. Before initialization, Statsig SDKs don't have the latest values in memory and may return stale values or none at all.

Unlike Server SDK initialization, which happens at server startup, Client SDK initialization happens when a screen renders, so initialization has more impact on user experience. Statsig offers several client initialization methods to tune performance to your needs.

{% tabs %}
{% tab title="Client SDKs" %}
## General initialization flow

`initialize` takes an SDK key and `StatsigUser` object. The SDK then:

1. Check local storage for cached values. The SDK caches previous evaluations locally so they're available in the next session if there is no successful network call.
2. Create a `STATSIG_STABLE_ID`: an ID that stays consistent per device, which is useful for logged-out experiments.
3. Set the SDK as initialized so checks don't throw errors. Checks return cached values or defaults.
4. Issue a network request to Statsig to get the latest values for all gates/experiments/configs/layers/autotunes for the given user. If the project definition hasn't changed from the most recent cached values, this request may succeed without returning new data.
5. Resolve the asynchronous `initialize` call. If the request to the server failed, the SDK uses cached values or returns defaults for this session.

Depending on when you check a gate or experiment after initializing, fresh values may not be available yet. Awaiting initialization resolves this, with some performance tradeoffs (described in Client initialization strategies).

## Client initialization strategies

Below are the various strategies summarized at a high level, ordered from most common to least common:

* [**Asynchronous Initialization (Awaited)**](#1-asynchronous-initialization-awaited): Wait for the initialization network call to finish before rendering content.
* [**Bootstrap Initialization**](#2-bootstrap-initialization): Generate the assignment values on your own server, and pass them down with other request, resulting in zero-latency rendering. Provides both low latency and fresh assignments, but requires additional engineering effort.
* [**Asynchronous Initialization (Not Awaited)**](#3-asynchronous-initialization-not-awaited): Don't await the return of the initialization network call. This ensures immediate rendering, but in a state that reflects stale assignments or no assignments available.
* [**Synchronous Initialization**](#4-synchronous-initialization): Renders immediately, but with stale or no assignments available. Statsig never assigns first-visit users to gates and experiments.

| Method | Speed-to-render? | Render consistency? | Latest content? | Engineering Complexity? |
|-------------------------|---------------------|-----------------|-----------------|------------------|
| **Explanation** | When I visit the webpage, how fast does the content appear? | Does the content ever change/flicker? | Does the user ever see an out-of-date config value? | How easy is this to implement? |
| Await InitializeAsync() | ❌ Slow | ✅ Good | ✅ Yes | ✅ Easy |
| InitializeAsync() | ✅ Fast | ❌ Poor | ✅ Yes | ✅ Easy |
| InitializeSync() | ✅ Fast | ✅ Good | ❌ No | ✅ Easy |
| BootstrapInit | ✅ Fast | ✅ Good | ✅ Yes | ❌ Extra Effort |

### 1. Asynchronous initialization - awaited

> Ensures latest assignments but requires a loading state

When calling `StatsigClient.initializeAsync`, the client loads values from the cache and fetches the latest values from the network. This approach waits for the latest values before rendering. It isn't immediate, but ensures the values are up to date.

{% codetabs %}
```tsx React Example
const { client, isLoading } = useClientAsyncInit(
  YOUR_CLIENT_KEY,
  { userID: "u_123" }
);

if (isLoading) {
  return <div>Loading...</div>;
}

// Continue with initialized client
```

```js JavaScript Example
const client = new StatsigClient(YOUR_CLIENT_KEY, { userID: "u_123" });
await client.initializeAsync();

// Client is now initialized with latest values
```
{% /codetabs %}

### 2. Bootstrap initialization

> Ensures both latest assignments with no rendering latency

Bootstrapping allows you to initialize the client with a JSON string. Values are immediately available without the client making any network requests. You're responsible for keeping these values up to date.

Your server serves the configuration payload to your client app on page load (for web implementations) or during app launch (for mobile implementations).

{% codetabs %}
```tsx React Bootstrap
// Server-generated initialization values
const initValues = getStatsigValuesFromServer(user);

const client = useClientBootstrapInit(
  YOUR_CLIENT_KEY,
  { userID: "u_123" },
  initValues
);

// Client renders immediately with server values — no network request
```

```js JavaScript Bootstrap
const bootstrapValues = getInitializationValuesFromServer();
const client = new StatsigClient(YOUR_CLIENT_KEY, { userID: "u_123" });
client.dataAdapter.setData(bootstrapValues);
client.initializeSync();
```
{% /codetabs %}

### 3. Asynchronous initialization - not awaited

To fetch the latest values without awaiting the asynchronous call, call `initializeAsync` and catch the promise. This approach provides immediate rendering with cached values initially, then updates to the latest values mid-session.

{% callout type="warning" %}
Be aware that the values may switch when you check them a second time after the SDK loads the latest values.
{% /callout %}

### 4. Synchronous initialization

> Ensures immediate rendering but uses cached assignments (when available)

When calling `StatsigClient.initializeSync`, the client uses cached values if they're available. The SDK fetches new values in the background and updates the cache. This approach provides immediate rendering, but values may be stale or absent during the first session.
{% /tab %}

{% tab title="Server SDKs" %}
## General initialization flow

Server SDKs require only a secret key to initialize. Because servers handle many users, server SDKs download all rules and configurations in your project and evaluate them in real time for each user. The Server SDK initialization process:

1. Your server checks if you have locally cached values (which you can set up with a [DataAdapter](https://docs.statsig.com/server/concepts/data_store/)).
2. If your server found values on the last call, it's ready for checks with the reason "DataAdapter". Whether it found local data or not, it next goes to the network to find updated values.
3. The server retrieves updated rules from the network, and is now ready for checks even if it didn't find values in step 1.
4. Going forward, the server retrieves new values every 10 seconds from the network, updating the locally cached values each time.

DataAdapters provide resilience and ensure your server is ready to serve requests as soon as it starts up, without waiting for a network round trip. This is especially useful for short-lived or serverless instances. For advanced setups, Statsig offers a [Forward Proxy](https://docs.statsig.com/server/concepts/forward_proxy/) for additional resilience.

{% codetabs %}
```js Node.js Initialization
import { Statsig, StatsigUser } from '@statsig/statsig-node-core';

const statsig = new Statsig("YOUR_SERVER_KEY");
await statsig.initialize();

// Server SDK is now ready to evaluate gates/experiments for any user
const user = new StatsigUser({ userID: "123" });
const gate = statsig.checkGate(user, "my_gate");
```

```python Python Initialization
from statsig_python_core import Statsig, StatsigUser

statsig = Statsig("YOUR_SERVER_KEY")
statsig.initialize().wait()

# Server SDK is now ready
user = StatsigUser("123")
gate = statsig.check_gate(user, "my_gate")
```
{% /codetabs %}
{% /tab %}
{% /tabs %}
