On this page

Go Server Core SDK (Beta)

Statsig's next-gen Go Server SDK built on our [Server Core](/server-core) framework

Setup the SDK

  1. Install the SDK

    Using the go get CLI, install the latest version of the SDK:

    plaintext
    go get github.com/statsig-io/statsig-go-core@latest
    

    Or add a dependency on the most recent version in go.mod:

    plaintext
    require (
      github.com/statsig-io/statsig-go-core v0.10.2-beta
    )
    
    Go to the Releases tab in GitHub for the latest versions.

    :::note go get requires a Go module project with a go.mod file. :::

  2. Initialize the SDK

    After installation, initialize the SDK using a Server Secret Key from the Statsig console.

    Server Secret Keys should always be kept 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.

    go
    import (
        "log"
    
        statsig "github.com/statsig-io/statsig-go-core"
    )
    			
    options, err := statsig.NewOptionsBuilder().
        WithOutputLogLevel("DEBUG").
        Build()
    if err != nil {
        log.Fatalf("failed to build options: %v", err)
    }
    
    s, err := statsig.NewStatsigWithOptions("secret-key", options)
    if err != nil {
        log.Fatalf("failed to create Statsig client: %v", err)
    }
    
    s.Initialize()
    
    initialize performs a network request. After initialize completes, virtually all SDK operations are synchronous (refer to Evaluating Feature Gates in the Statsig SDK). The SDK fetches updates from Statsig in the background, independent of your API calls.

Working with the SDK

Checking a Feature Flag/Gate

After the SDK is initialized, you can fetch a Feature Gate. 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). To check a gate for a user:
go
user, _ := statsig.NewUserBuilderWithUserID("a-user").Build()

// Basic check
if s.CheckGate(user, "a_gate") {
    // Gate is on, enable new feature
} else {
    // Gate is off
}

// With options (e.g., disable automatic exposure logging)
options := &statsig.FeatureGateEvaluationOptions{DisableExposureLogging: true}
s.CheckGateWithOptions(user, "a_gate", options)

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. The API is similar to Feature Gates, but returns a JSON object from which you can retrieve typed parameters. For example:
go
user, _ := statsig.NewUserBuilderWithUserID("a-user").Build()

// You can disable exposure logging for this specific check
dynamicConfigOptions := &statsig.DynamicConfigEvaluationOptions{DisableExposureLogging: false}

dynamic_config := "a_config"
config := s.GetDynamicConfigWithOptions(user, dynamic_config, dynamicConfigOptions)

// Access the config values
str_val := config.GetString("str_val", "default_str_val") // returns String
int_val := config.GetNumber("number_val", 100) // returns float64
bool_val := config.GetBool("bool_val", false) // returns bool
interface_val := config.GetSlice("interface_val", []any{"default_interface_val"}) // returns []any
map_val := config.GetMap("map_val", map[string]any{"default": "value"}) // returns map[string]interface{}

// The config object also provides metadata about the evaluation
fmt.Println(config.RuleID) // The ID of the rule that served this config
fmt.Println(config.IDType) // The type of the evaluation (experiment, config, etc)

Getting a Layer/Experiment

Layers/Experiments let you run A/B/n experiments. Two APIs are available, but layers are recommended because layers make parameters reusable and support mutually exclusive experiments.
go
user, _ := statsig.NewUserBuilderWithUserID("a-user").Build()

// Getting values with GetExperiment
experimentOptions := &statsig.ExperimentEvaluationOptions{DisableExposureLogging: false}

experiment := s.GetExperimentWithOptions(user, "a_test_experiment", experimentOptions)
str_val := experiment.GetString("str_val", "default_str_val") // returns String
int_val := experiment.GetNumber("number_val", 100) // returns float64

// Getting values with GetLayer
layerOptions := &statsig.LayerEvaluationOptions{DisableExposureLogging: false}

layer := s.GetLayerWithOptions(user, "a_test_experiment", layerOptions)
str_val := layer.GetString("str_val", "default_str_val") // returns String
int_val := layer.GetNumber("number_val", 100) // returns float64

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:

go
user, _ := statsig.NewUserBuilderWithUserID("a-user").Build()

options := &statsig.FeatureGateEvaluationOptions{DisableExposureLogging: false}
featureGate := s.GetFeatureGateWithOptions(user, "a_gate", options)

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:

go
user, _ := statsig.NewUserBuilderWithUserID("a-user").Build()

event := statsig.EventPayload{
    EventName: "sample_event",
    Value:     "event",
    Metadata: map[string]string{
        "val_1": "log val 1",
    },
}

s.LogEvent(user, event)

Manual exposures

By default, the SDK automatically logs an exposure event when you check a gate, get a config, get an experiment, or call get() on a layer parameter. To delay exposure logging until the user actually uses the feature, use manual exposures.

All main SDK functions (CheckGate, GetDynamicConfig, GetExperiment, GetLayer) accept an optional options parameter with a DisableExposureLogging field. When set to true, the SDK doesn't automatically log an exposure event. You can then manually log the exposure using the corresponding manual exposure logging method:

go
user, _ := statsig.NewUserBuilderWithUserID("a-user").Build()
options := &statsig.FeatureGateEvaluationOptions{DisableExposureLogging: true}
result := s.CheckGateWithOptions(user, "a_gate_name", options)
go
s.ManuallyLogFeatureGateExposure(user, "gate_name")

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 to enable advanced gate and config conditions (such as country or OS/browser checks) and to measure experiment impact accurately. As explained in why an ID is always required for server SDKs, at least one identifier (userID or customID) is required to provide a consistent experience for a given user.

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 used for evaluation but not forwarded to any integrations. Use them for PII or sensitive data that you don't want to send to third-party services.

Statsig Options

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

Parameters

SpecsUrlstring

Custom URL for fetching feature specifications.

LogEventUrlstring

Custom URL for logging events.

Environmentstring

Environment parameter for evaluation.

EventLoggingFlushIntervalMsnumber

How often events are flushed to Statsig servers (in milliseconds).

EventLoggingMaxQueueSizenumber

Maximum number of events to queue before forcing a flush.

SpecsSyncIntervalMsnumber

How often the SDK updates specifications from Statsig servers (in milliseconds).

OutputLogLevelstring

Controls the verbosity of SDK logs.

DisableCountryLookupboolean

Disables country lookup based on IP address. Set to true to improve performance if country-based targeting is not needed.

DisableUserAgentParsingboolean

Disables user agent parsing. Set to true to improve performance if device/browser-based targeting is not needed.

WaitForCountryLookupInitboolean

When set to true, the SDK waits for country lookup data (such as GeoIP or YAML files) to fully load during initialization. This may add approximately 1 second to startup time, but ensures that IP-to-country parsing is ready at evaluation time.

WaitForUserAgentInitboolean

When set to true, the SDK waits until user agent parsing data is fully loaded during initialization. This may add approximately 1 second to startup time, but ensures that parsing of the user's userAgent string into fields such as browserName, browserVersion, systemName, systemVersion, and appVersion is ready before any evaluations.

EnableIdListsboolean

Enables downloading ID lists; set to false to skip ID list syncing.

IdListsUrlstring

Custom URL for fetching ID lists.

IdListsSyncIntervalMsnumber

How often the SDK syncs ID lists (in milliseconds).

DisableAllLoggingboolean

When set to true, the SDK doesn't log any events or exposures.

DisableNetworkboolean

When set to true, the SDK doesn't make any network requests.

GlobalCustomFieldsstring

JSON string of custom fields that should be appended to every evaluation.

ObservabilityClientRefnumber

Internal reference for a custom observability client created through the SDK.

DataStoreRefnumber

Internal reference for a custom data store adapter created through the SDK.

PersistentStorageRefnumber

Internal reference for a persistent storage adapter created through the SDK.

InitTimeoutMsnumber

Maximum time in milliseconds to wait for SDK initialization to complete. If initialization takes longer than this timeout, the SDK will continue to operate but may return default values until initialization completes.

FallbackToStatsigApiboolean

When set to true, the SDK falls back to using the Statsig API directly if custom adapters (like local file adapters) fail to load configurations.

Proxy and custom network routing

The Go Server Core SDK currently documents endpoint overrides rather than a dedicated outbound proxy config. Use WithSpecsUrl(...), WithLogEventUrl(...), and WithIdListsUrl(...) to route Statsig network calls through your own endpoints or proxy layer.


Example options usage

go
import (
    statsig "github.com/statsig-io/statsig-go-core"
)

// Initialize StatsigOptions with custom parameters
options, err := statsig.NewOptionsBuilder().
    WithSpecsUrl("https://example.com/specsUrl").
    WithLogEventUrl("https://example.com/logUrl").
    WithEnvironment("production").
    WithEventLoggingFlushIntervalMs(2000).
    WithEventLoggingMaxQueueSize(5000).
    WithSpecsSyncIntervalMs(1000).
    WithOutputLogLevel("DEBUG").
    WithDisableCountryLookup(true).
    WithDisableUserAgentParsing(true).
    WithWaitForCountryLookupInit(false).
    WithEnableIdLists(true).
    WithIdListsSyncIntervalMs(60000).
    WithInitTimeoutMs(3000).
    WithFallbackToStatsigApi(false).
    Build()
if err != nil {
    // handle options build error
}

// Pass the options object when initializing the Statsig client
s, err := statsig.NewStatsigWithOptions("secret-key", options)
if err != nil {
    // handle init error
}
s.Initialize()

Shutting Statsig Down

Because events are batched and periodically flushed, some events may not have been sent when your app or server shuts down. To ensure all logged events are flushed, call shutdown() before shutting down your app or server:

go
// Method signature
func (s *Statsig) Shutdown() {}

// example usage
s, err := statsig.NewStatsig("secret-key")
s.Initialize()
s.Shutdown()

Flush events

go
// Method signature
func (s *Statsig) FlushEvents() {}

// example usage
s, err := statsig.NewStatsig("secret-key")
s.Initialize()
s.FlushEvents()

FAQ

Installation FAQs

How do I fix undefined symbol errors/linker errors?

You may need to reset your environment variables to those found in the statsig.env or statsig.env.ps1 file generated during the post-install script. Running the command sets the environment variables for the current terminal session. Add the variables to your .bashrc, .zshrc, or .ps1 file to load them automatically.

Was this helpful?