# Fastly

Statsig offers a suite of integration tools for use with Fastly:

* Statsig automatically pushes project changes to Fastly KV or Config Store, providing low-latency SDK startup.
* Statsig provides a Fastly helper that handles client initialization and event flushing, so you can focus on your business logic.

{% steps %}
{% step %}
#### Configure integration

First, enable the Fastly integration in the Statsig Console.

Navigate to [Project Settings -> Integrations](https://console.statsig.com/integrations), and then select Fastly.

Input the following:

* **Fastly API Key**: Find this in Fastly portal under **Account** -> **API Tokens**.
  * Create an **Automation Token** with:
    * **global** and **global:read** scope
* **Store Type**: Select **"Config Store"** or **"KV Store"** depending on your storage type.
* **Config Store ID** OR **KV Store ID**: Your Store ID

There's also an option to filter the configs synced into your KV namespace by a Target App. Enable this option as the size of your config payload grows. For now, you can leave the option unchecked.

After filling this out, select **Enable**.

Within a minute, the Statsig backend generates a config payload from your Statsig project and pushes it into your store. Under your Config or KV Store, look for a key starting with the prefix `statsig-`. This is the `key` associated with your Statsig config specs in your store. Note this key, as it's required later.
{% /step %}

{% step %}
#### Install the Statsig SDK

Install the Statsig serverless SDK:

```bash
npm install @statsig/serverless-client
```
{% /step %}

{% step %}
#### Import the statsig SDK

Import the Statsig Helper:

```javascript
import { handleWithStatsig} from "@statsig/serverless-client/fastly";
```
{% /step %}

{% step %}
#### Use the SDK

```javascript
handleWithStatsig(handler, params)
```

The helper method takes two arguments:

* `handler` This is your Fastly Compute code.
* `params : StatsigFastlyHandlerParams`

  | Parameter | Optional | Type | Description |
  |-----------|----------|------|-------------|
  | `statsigSdkKey` | No | `string` | Your Statsig client API key |
  | `fastlyStoreType` | No | `string` | Either `kv` or `config`, signifying your Fastly store type |
  | `storeId` | No | `string` | Your KV or Config store id |
  | `keyId` | No | `string` | The key storing your Statsig config specs in your Fastly store |
  | `apiToken` | No | `string` | Your Fastly API token used to authenticate requests to the Fastly API |
  | `statsigOptions` | Yes | `StatsigOptions` | See StatsigOptions [here](https://docs.statsig.com/client/javascript-sdk#statsig-options) |

  For best practice: store `statsigSdkKey` and `apiToken` in a Fastly [Secret Store](https://www.fastly.com/documentation/guides/compute/edge-data-storage/working-with-secret-stores/)

### Example usage

```javascript index.js
import { handleWithStatsig} from "@statsig/serverless-client/fastly";


async function myHandler(event, client) {

    const user = { userID: Math.random().toString().substring(2, 5) };
    const res = client.checkGate("pass_gate", user);
    client.logEvent("pass_gate", user);
    return new Response(
    JSON.stringify({ res, user }),
    { 
      status: 200,
      headers: { 'Content-Type': 'application/json' }
    }
  );
}

const handleRequest =  handleWithStatsig(myHandler,{
    statsigSdkKey: "client-LhxVWHSeZt2uor***********",
    fastlyStoreType: "kv",
    storeId:"7b12fn*********",
    keyId:"statsig-3htllY8XxFsJ*****",
    apiToken:"7NaRxS6R**********"
})

addEventListener('fetch', (event) => event.respondWith(handleRequest(event)));

```
{% /step %}
{% /steps %}

The helper automatically:

* Initializes the Statsig Client with config specs from your KV or Config store
* Executes your handler code (your business logic and Statsig usage)
* Flushes all events after your handler completes execution
* Cleans up resources

### Advanced usage

{% accordion title="Advanced/manual usage" %}
Use the advanced or manual setup if:

* You need fine-grained control over initialization timing
* You need fine-grained control over event flushing timing
* You need to customize error handling behavior

### Prerequisites

1. Completed the [Statsig Fastly integration setup](#configure-integration)

{% steps %}
{% step %}
#### Install the Statsig SDK

Install the Statsig serverless SDK:

```bash
npm install @statsig/serverless-client
```
{% /step %}

{% step %}
#### Import the statsig SDK

Import the Fastly client:

```javascript
import { StatsigFastlyClient} from "@statsig/serverless-client/fastly";
```
{% /step %}

{% step %}
#### Creating a `StatsigFastlyClient` instance

```javascript
const client = new StatsigFastlyClient("<Your Statsig client key>");
```

The client instantiation takes two arguments:

* `sdkKey : string` Your Statsig client API key. Available from the [Project Settings](https://console.statsig.com/api_keys) page in the Statsig Console. Used to authenticate your requests.
* `options : StatsigOptions` For more options, go to [StatsigOptions](https://docs.statsig.com/client/javascript-sdk#statsig-options).

For best practice: store `sdkKey` in a Fastly [Secret Store](https://www.fastly.com/documentation/guides/compute/edge-data-storage/working-with-secret-stores/)
{% /step %}

{% step %}
### Client initialization

The following line initializes the client by loading feature gate and experiment configurations directly from your Fastly KV or Config store.

```javascript
const initResult = await client.initializeFromFastly(<YOUR_FASTLY_STORE_TYPE>,
  <YOUR_STORE_ID>,
  <KEY_ASSOCIATED_WITH_STASIG_SPECS>,
  <YOUR_FASTLY_API_KEY>
);
```

The client initialization takes four arguments:

* `fastlyStoreType : string` This is the Fastly store type you're using represented by `kv` or `config`
* `storeId : string` The id of your Fastly store
* `keyId : string` The key storing the Statsig config specs in your store
* `apiToken : string` Your Fastly API token

For best practice: store `apiToken` in a Fastly [Secret Store](https://www.fastly.com/documentation/guides/compute/edge-data-storage/working-with-secret-stores/)
{% /step %}

{% step %}
#### Checking a Gate

```javascript
const value = client.checkGate("pass_gate", user);
```

The `checkGate` method takes two arguments:

* `name : string` The name of the Statsig gate you're checking.
* `user : StatsigUser` The Statsig user object for whom you check the gate. For more information on the user object, refer to [StatsigUser introduction](https://docs.statsig.com/sdks/user#introduction-to-the-statsiguser-object).

Refer to the [Javascript on-device evaluation SDK documentation](https://docs.statsig.com/client/jsOnDeviceEvaluationSDK) for how to check other entities like experiments and dynamic configs.
{% /step %}

{% step %}
#### Logging an event

```javascript
client.logEvent('fastly_gate_check', user, value.toString());
```

The `logEvent` method takes two parameters:

* `eventOrName : string | StatsigEvent` The name and details of the event you're logging.
* `user : StatsigUser` The Statsig user object for whom you log the event.
* `value : string` A value to associate with this event.

For more information on event logging, refer to [Logging an event](https://docs.statsig.com/client/jsOnDeviceEvaluationSDK#logging-an-event).
{% /step %}

{% step %}
#### Flushing events

```javascript
event.waitUntil(client.flush());
```

This flushes all events from the SDK to Statsig. Without this call, diagnostic information and logged event data don't appear in the Statsig Console.
{% /step %}
{% /steps %}

#### Putting it all together

```javascript
import { StatsigFastlyClient } from "@statsig/serverless-client/fastly";

addEventListener("fetch", (event) => event.respondWith(handleRequest(event)));

async function handleRequest(event) {

    const client = new StatsigFastlyClient("client-LhxVWHSeZt2uor********");

    const initResult = await client.initialzeFromFastly(
      "kv",
      "7b12fnfm7po7*********",
      "statsig-3htllY8X**********",
      "7NaRxS6RMGE-DTp*******"
    );

    const user = { userID: Math.random().toString().substring(2, 5) };
    const value = client.checkGate("pass_gate", user);
    client.logEvent("fastly_gate_check", user, value.toString());
    event.waitUntil(client.flush());
    
    return new Response(JSON.stringify({ kv, user }), {
      status: 200,
      headers: { "Content-Type": "application/json" },
    });

}

```

## Other considerations

### Polling for updates v5.13.0+

The SDK can't poll for updates across requests because Fastly doesn't allow timers. To optimize for edge use cases, there's no API to detect updates to your config specs. When you make a change to your project definition in the Statsig console, Statsig propagates the changes to the KV or Config store. The changes take effect the next time you initialize the StatsigFastly client.

### Flushing events v4.16.0+

The SDK enqueues logged events and flushes them in batches. To flush events properly, call flush using `event.waitUntil()`. This keeps the request handler alive until the SDK flushes events without blocking the response.

```
event.waitUntil(statsig.flush());
```
{% /accordion %}

To check evaluations, go to the gate you created for this example and view the evaluations in the Diagnostics tab. To check logged events, in the **Statsig Console**, go to **Data** -> **Events**.

### Size limits

Fastly Config Store has maximum size limits that may prevent Statsig from pushing configs into Fastly. Go to [the Fastly documentation](https://docs.fastly.com/products/edge-data-storage) for the latest Config Store limits. If your payload continues to grow, you need to set the option to filter the payload by a Target App in the integration settings.

### Unsupported features

Statsig doesn't sync ID Lists into Fastly KVs or Config Stores. If you rely on large (>1000) ID lists, you can't check them in your Fastly compute services.
