Skip to main content

Forward Proxy

Statsig Forward Proxy

The Statsig Forward Proxy is a service that we developed to be hosted and run in your own infrastructure. If SDKs are configured to use the foward proxy, it provides a closer, but also more reliable hop for retrieving Statsig dependent configurations from within your infrastructure instead of reaching out to our networks.

The expected benefits of using the proxy are:

  1. Reduced dependency on Statsig Infrastructure Availability
  2. Improved performance through localization of download_config_spec to your cluster
  3. Improved cost savings and reduced network overhead through minimizing requests to Statsig Infrastructure
  4. Improved consistency of configurations, as the forward proxy becomes an articulation point for serving configs
  5. Support for cool features such as a streaming API through GRPC

If you're interested in deploying the proxy, you can find more details in the public repository here.

If you have any questions about how to deploy, or need assistance, feel free to reachout to us on our slack channel or create a new github issue.

How Forward Proxy works

The forward proxy works by setting up a local http or grpc server. When requests are made to the forward proxy, only the initial request is blocking, after that, a background loop is spawned which keeps configurations up to date without impacting the hot path for serving configurations.

While providing this capability, the forward proxy also provides other benefits such the ability to enable backup caches and monitoring through technologies such as Redis and Statsd.

Integration with SDK

info

NOTE:

Java/Kotlin, Python, and NodeJS SDKs have beta versions which support a full integration with Statsig Forward Proxy including GRPC Mode integration with Statsig Forward Proxy. For other server sdks, there is no support on full integration yet, you can override download_config_spec api in StatsigOptions in order to integrate. You should use carefully and consult us.

You can now configure SDK network using different network protocol to integrate with Statsig Forward Proxy for different endpoints. There are 3 network endpoints SDK make requests to download_config_specs,get_id_lists, and log_events, and you can configure each endpoint 1. protocol being used 2. proxy address.

Network protocol for different endpoints

For download_config_specs endpoint, where we get specs on evaluating gates/layers/experiments/configs

  1. http: the default protocol. If SDK is initialized with http, it will poll config updates in background thread.
  2. grpc_websocket: Establish a grpc streaming from SDK to statsig forward proxy, and listen to updates being pushed from proxy servers. You have to use statsig forward proxy or have a similar proxy server in order to use grpc streaming. Note: Not all SDKs support GRPC yet, if you have an SDK you want support for please reachout to our support channel on slack.
  3. grpc: Unary RPC, behave similarly to HTTP protocol, after initialization, SDK poll changes from forward proxy server in background thread.
warning

We are still adding support for log_events and get_id_lists endpoint within Forward Proxy

For get_id_lists endpoint, where we get big idlists

  1. http: the default protocol. If SDK is initialized with http, it will poll idlists from forward proxy server or statsig server.
  2. grpc_websocket: Not supported
  3. grpc: Not supported

For log_events endpoint, where we post exposure events and custom events.

  1. http: the default protocol. SDK will make POST Http request to flush all events to Statsig server, forward proxy server does not support this endpoint.
  2. grpc_websocket: Not supported yet.
  3. grpc: Not supported yet

Listen to Config Change Example

const statsigOptions = {
proxyConfigs: {
download_config_specs: {
proxyAddress: proxyAddress // Your proxy address
protocol: "grpc_websocket"
}
}
}
Statsig.initialize(server_key, statsigOptions)
// Statsig will use listen for config updates from statsig forward proxy using grpc_websocket protocl. And use http to get idlists and post log events from statsig servers.

For information on your specific SDK language, see the language specific docs in the left hand column.

Failover behavior

Initializaiton SDK remains the same behavior when forward proxy is being used. But there are several configurations you can use to improve the data availability during initialization. Default behavior is SDK will get from forward proxy. If DataAdapater is presented, get from DataAdapter first, and fallback to Forward Proxy if there is no value served from data adapter. There are several ways you can configure the behavior here.

  1. Set DataAdapter.should_be_use_as_initialization_backup_source = true, use forward proxy as primary source, if it fails, fallback to dataAdapter.
  2. Set defaultToStatsigAPI = true, if you want to default to statsig api when both sources failed.

Config Sync (Post initialization) If sdk is using grpc_websocket protocol, meaning sdk is in a listening mode for any config changes, it will

  1. Retry connecting to forward proxy, with exponenetial backoff, 10s, 50s, 250s, 1250s ... until it reconnects, limit fo r retry is 10 times.
  2. If 4th retry still fails, sdk will start polling from from Statsig endpoint. Use StatsigOptions.pollingInterval to control how often it
  3. While sdk polling from Statsig endpoint, sdk will keep retrying until it connected,

Coordinate SDK DataAdapater / DataStore with Forward Proxy Cache service

In order to increase reliability of SDK during initialization, setup DataStore will help in case Forward Proxy is not available when initialized. If DataStore is set, SDK will try initailize with values from dataStore, and sync (listen or polling depends on setup) from forward proxy in background after initialization. It's recommended for SDK and Forward Proxy to share the same cache service for consistency and reduce cache I/O.

Example on DataStore setup in python:

class DataAdapter(IDataStore):
def __init__(self):
self.redis_cache = ExampleCache()

def get(self, key: str):
self.cache.get(key)

def set(self, key: str):
# Don't implement set method if you are share the same cache between forward proxy and sdk, forward proxy will write to cache
pass

def shutdown(self):
self.cache.shutdown()