
A common question when configuring Statsig is how to handle potential points of failure. For example, if there is a Statsig API outage, can your integration continue to function?

Yes. Your server SDK continues to operate normally, serving the most recent set of known values in response to calls like `checkGate`, `getConfig`, `getExperiment`, and `getLayer`. After the API recovers, your SDK automatically re-fetches the most up-to-date version of your project.

Starting a new server or SDK instance while Statsig is down is a different scenario. The `DataAdapter`/`DataStore` addresses this case.

## DataAdapter (or DataStore)

DataAdapters let you plug in your own storage solution as a cache that the Statsig Server SDKs use to load your project configurations (all experiments, configs, gates, and their targeting and allocation rules). Key use cases include reducing dependency on Statsig servers for initialization, improving initialization time by loading config from a local data store, and minimizing network I/O. DataAdapters implement a simple API: `initialize`, `get`, `set`, and `shutdown`.

### Recommended implementation

In most cases, **your web servers should only implement the read path (`get`)**.
Leaving the write path (`set`) empty is the best practice. If every SDK instance writes to the store on every update, this creates unnecessary contention and duplication.

Instead, you should have a single source of truth that keeps your datastore up-to-date:

* Run a **separate out-of-band service** that implements the SDK and is responsible for writing updates into the datastore using `set`.
* Or, use a **cron job / periodic job** to fetch the config from the Statsig CDN endpoint and update your datastore under the correct cache keys (`statsig.cache`, `statsig.id_lists`, and `statsig.id_lists::{list_name}`).

The Statsig SDK already handles this refresh logic by default, so separating read and write responsibilities is the cleanest and most reliable pattern.

### Data adapter logic

* When the Statsig SDK is initialized with a DataAdapter, it first attempts to load config using `DataAdapter.get`.
  * If the entry exists, the SDK uses it.
  * If the entry doesn't exist and `localMode` isn't enabled, the SDK fetches the config from Statsig servers and (if you have a writer service) persists it using `DataAdapter.set`.
* After initialization, the SDK continues to poll Statsig servers for updates and saves them back to your data store when available (if you have implemented `set` and designated a writer service).
* If the SDK client is initialized with `localMode=true`, this will disable all network fetches from Statsig.
* The cache keys used to be:
  * `statsig.cache` → config specs
  * `statsig.id_lists` → lookup of id lists
  * `statsig.id_lists::{list_name}` → actual id list values
* but in the latest node and server core sdks, the format has changed:
  * `statsig|{path}|{format}|{hashedSDKKey}` where `path` is `/v1/download_config_specs` or `/v1/get_id_lists`, format is `plain_text`, and the `djb2` has of the sdk key is the last bit
  * the SDK will handle this for you, reach out if you are trying to recreate this path yourself to double check

{% callout type="note" %}
Most DataAdapters are used only for the `initialize` path for getting a project definition.

At the time of this writing, only `Node.js`, `Ruby`, `Go`, `Java` and `.NET` support polling for updates.\
If you're interested in using a DataAdapter as the source of truth indefinitely, reach out in the [Slack community](https://statsig.com/slack) and let us know which language this would be useful for!
{% /callout %}

For information on your specific SDK language, go to the language-specific docs in the left-hand column.
