On this page

Experiment JVM SDK

Official documentation for Amplitude Experiment's server-side JVM SDK implementation. Use this SDK in either Java or Kotlin server-side implementations.

This documentation has separate sections for remote and local evaluation:

Remote evaluation

Implements fetching variants for a user using remote evaluation.

Install

Install the JVM Server SDK using Gradle.

groovy
implementation "com.amplitude:experiment-jvm-server:<VERSION>"

Initialize remote

Initialize the SDK client in your server on startup. The deployment key argument you pass to the apiKey parameter must live within the same project that you are sending analytics events to.

kotlin
fun initializeRemote(
    apiKey: String,
    config: RemoteEvaluationConfig = RemoteEvaluationConfig()
): RemoteEvaluationClient
ParameterRequirementDescription
apiKeyrequiredThe deployment key that authorizes fetch requests and determines which flags to evaluate for the user.
configoptionalThe client configuration used to customize SDK client behavior.
kotlin
val experiment = Experiment.initializeRemote("<DEPLOYMENT_KEY>")

Configuration

Configure the SDK client during initialization.

EU data center

If you're using Amplitude's EU data center, configure the serverZone option on initialization.

NameDescriptionDefault Value
debugSet to true to enable debug logging.false
logLevelThe minimum log level to output. Options: VERBOSE, DEBUG, INFO, WARN, ERROR, DISABLE. Go to custom logging.ERROR
loggerProviderCustom logger implementation. Implement the LoggerProvider interface to integrate with your logging solution. Go to custom logging.DefaultLogger which outputs to stdout
serverZoneThe Amplitude data center to use. Either ServerZone.US or ServerZone.EU.ServerZone.US
serverUrlThe host to fetch flag configurations from.https://api.lab.amplitude.com
fetchTimeoutMillisThe timeout for fetching variants in milliseconds.500
fetchRetriesThe number of retries to attempt if a request to fetch variants fails.1
fetchRetryBackoffMinMillisThe minimum (initial) backoff after a request to fetch variants fails. The SDK scales this delay by the fetchRetryBackoffScalar0
fetchRetryBackoffMaxMillisThe maximum backoff between retries. If the scaled backoff becomes greater than the max, the SDK uses the max for all subsequent requests10000
fetchRetryBackoffScalarScales the minimum backoff exponentially.1

CohortSyncConfig

NameDescriptionDefault Value
apiKeyThe analytics API key and NOT the experiment deployment keyrequired
secretKeyThe analytics secret keyrequired
maxCohortSizeThe maximum size of cohort that the SDK downloads. Cohorts larger than this size won't download.2147483647
cohortPollingIntervalMillisThe interval, in milliseconds, to poll Amplitude for cohort updates (60000 minimum).60000
cohortServerUrlThe cohort server endpoint from which to fetch cohort data. For hitting the EU data center, set serverZone to ServerZone.EU. Setting this value overrides serverZone defaults.https://cohort-v2.lab.amplitude.com

Fetch

Fetches variants for a user and returns the results. The function remote evaluates the user for flags associated with the deployment used to initialize the SDK client.

kotlin
fun fetch(user: ExperimentUser, fetchOptions: FetchOptions? = null): CompletableFuture<Map<String, Variant>>
ParameterRequirementDescription
userrequiredThe user for whom to fetch variants.
fetchOptionsoptionalThe options for the fetch request.

FetchOptions

NameDescriptionDefault Value
tracksExposureTo track or not track an exposure event for this fetch request. If null, uses the server's default behavior (doesn't track exposure).null
tracksAssignmentTo track or not track an assignment event for this fetch request. If null, uses the server's default behavior (does track assignment).null
kotlin
val user = ExperimentUser.builder()
    .userId("user@company.com")
    .deviceId("abcdefg")
    .userProperty("premium", true)
    .build()
val variants = try {
    experiment.fetch(user).get()
} catch (e: Exception) {
    e.printStackTrace()
    return
}

After fetching variants for a user, you may to access the variant for a specific flag.

kotlin
val variant = variants["<FLAG_KEY>"]
if (variant?.value == "on") {
    // Flag is on
} else {
    // Flag is off
}

Local evaluation

Implements evaluating variants for a user using local evaluation. If you plan to use local evaluation, understand the tradeoffs.

Install

Install the JVM Server SDK using Maven or Gradle.

groovy
implementation "com.amplitude:experiment-jvm-server:<VERSION>"

Quick start

  1. Initialize the local evaluation client.
  2. Start the local evaluation client.
  3. Evaluate a user.
kotlin
// (1) Initialize the local evaluation client with a server deployment key.
val experiment = Experiment.initializeLocal(
    "<DEPLOYMENT_KEY>",
    // (Recommended) Enable local evaluation cohort targeting.
    LocalEvaluationConfig.builder()
        .cohortSyncConfig(CohortSyncConfig("<API_KEY>", "<SECRET_KEY>"))
        .build()
)

// (2) Start the local evaluation client.
experiment.start()

// (3) Evaluate a user.
val user = ExperimentUser.builder()
    .userId("user@company.com")
    .deviceId("abcdefg")
    .userProperty("premium", true)
    .build()
val variants = experiment.evaluate(user)

Initialize local

Initializes a local evaluation client.

Server deployment key

You must initialize the local evaluation client with a server deployment key to get access to local evaluation flag configs.

kotlin
fun initializeLocal(
    apiKey: String,
    config: LocalEvaluationConfig = LocalEvaluationConfig(),
): LocalEvaluationClient
ParameterRequirementDescription
apiKeyrequiredThe server deployment key that authorizes fetch requests and determines which flags to evaluate for the user.
configoptionalThe client configuration used to customize SDK client behavior.

Flag streaming

Use the streamUpdates configuration to push flag config updates to the SDK (default false), instead of polling every flagConfigPollingIntervalMillis milliseconds. The time for SDK to receive the update after saving is generally less than one second. The SDK reverts to polling if streaming fails. Configure flagConfigPollingIntervalMillis configuration to set the time flag configs take to update after modification (default 30s), as well for fallback.

Configuration

You can configure the SDK client on initialization.

EU data center

If you're using Amplitude's EU data center, configure the serverZone option on initialization.

LocalEvaluationConfig

NameDescriptionDefault Value
debugSet to true to enable debug logging.false
logLevelThe minimum log level to output. Options: VERBOSE, DEBUG, INFO, WARN, ERROR, DISABLE. Go to custom logging.ERROR
loggerProviderCustom logger implementation. Implement the LoggerProvider interface to integrate with your logging solution. Go to custom logging.DefaultLogger which outputs to stdout
serverZoneThe Amplitude data center to use. Either ServerZone.US or ServerZone.EU.ServerZone.US
serverUrlThe host to fetch flag configurations from.https://api.lab.amplitude.com
flagConfigPollingIntervalMillisThe interval to poll for updated flag configs after calling Start()30000
flagConfigPollerRequestTimeoutMillisThe timeout for the request made by the flag config poller10000
assignmentConfigurationDeprecated. Enable automatic assignment tracking for local evaluations.null
exposureConfigurationEnable exposure tracking for local evaluations.null
streamUpdatesEnable streaming to replace polling for receiving flag config updates. Instead of polling every second, Amplitude servers push updates to SDK generally within one second. If the stream fails for any reason, it reverts to polling automatically and retry streaming after some interval.false
streamServerUrlThe URL of the stream server.https://stream.lab.amplitude.com
streamFlagConnTimeoutMillisThe timeout for establishing a valid flag config stream. This includes time for establishing a connection to stream server and time for receiving initial flag configs.1500
cohortSyncConfigConfiguration to enable cohort downloading for local evaluation cohort targeting.null

AssignmentConfiguration

NameDescriptionDefault Value
api_keyThe analytics API key and NOT the experiment deployment keyrequired
cache_capacityThe maximum number of assignments stored in the assignment cache65536
eventUploadThresholdsetEventUploadThreshold() in the underlying Analytics SDK10
eventUploadPeriodMillissetEventUploadPeriodMillis() in the underlying Analytics SDK10000
useBatchModeuseBatchMode() in the underlying Analytics SDKtrue

ExposureConfiguration

NameDescriptionDefault Value
api_keyThe analytics API key and NOT the experiment deployment keyrequired
cache_capacityThe maximum number of exposures stored in the exposure cache65536
eventUploadThresholdsetEventUploadThreshold() in the underlying Analytics SDK10
eventUploadPeriodMillissetEventUploadPeriodMillis() in the underlying Analytics SDK10000
useBatchModeuseBatchMode() in the underlying Analytics SDKtrue

CohortSyncConfig

NameDescriptionDefault Value
apiKeyThe analytics API key and NOT the experiment deployment keyrequired
secretKeyThe analytics secret keyrequired
maxCohortSizeThe maximum size of cohort that the SDK downloads. Cohorts larger than this size won't download.2147483647
cohortPollingIntervalMillisThe interval, in milliseconds, to poll Amplitude for cohort updates (60000 minimum).60000

Start

Start the local evaluation client, pre-fetching local evaluation mode flag configs for evaluation and starting the flag config poller at the configured interval.

kotlin
fun start()

Wait for start() to return before calling evaluate() to ensure that flag configs are available for use in evaluation.

Stop

Shuts down the local evaluation client, stopping background processes for updating flag configs and cohorts.

kotlin
fun stop()

Evaluate

Executes the evaluation logic using the flags pre-fetched on start(). You must give evaluate a user object argument. You can optionally pass an array of flag keys if you require only a specific subset of flag variants.

Exposure tracking

Set exposureConfiguration to enable exposure tracking. Then, set tracksExposure to true in EvaluateOptions when calling evaluate().

kotlin
fun evaluate(user: ExperimentUser, flagKeys: List<String> = listOf(), evaluateOptions: EvaluateOptions? = null): Map<String, Variant>
ParameterRequirementDescription
userrequiredThe user to evaluate.
flagKeysoptionalSpecific flags or experiments to evaluate. If empty, the SDK evaluates all flags and experiments.
evaluateOptionsoptionalThe options for the evaluation request.
kotlin
// The user to evaluate
val user = ExperimentUser.builder()
    .userId("user@company.com")
    .deviceId("abcdefg")
    .userProperty("premium", true)
    .build()

// Evaluate all flag variants
val allVariants = experiment.evaluate(user)

// Evaluate a specific subset of flag variants
val specificVariants = experiment.evaluate(user, listOf(
    "<FLAG_KEY_1>",
    "<FLAG_KEY_2>",
))

// Access a variant
val variant = allVariants["<FLAG_KEY>"]
if (variant?.value == "on") {
    // Flag is on
} else {
    // Flag is off
}

EvaluateOptions

NameDescriptionDefault Value
tracksExposureIf true, the SDK tracks an exposure event for the evaluated variants.false

Local evaluation cohort targeting

Since version 1.4.0, the local evaluation SDK client supports downloading cohorts for local evaluation targeting. Configure the SDK using cohortSyncConfig with the analytics apiKey and secretKey on initialization to enable this support.

kotlin
val experiment = Experiment.initializeLocal(
    "<DEPLOYMENT_KEY>",
    // (Recommended) Enable local evaluation cohort targeting.
    LocalEvaluationConfig.builder()
        .cohortSyncConfig(CohortSyncConfig("<API_KEY>", "<SECRET_KEY>"))
        .build()
)

Custom logging

Set the logLevel configuration to adjust log verbosity, or implement the LoggerProvider interface to use your own logger.

Log levels

  • VERBOSE: Detailed debugging logs
  • DEBUG: Development and troubleshooting logs
  • INFO: General information
  • WARN: Warnings
  • ERROR: Errors only (default)
  • DISABLE: No logs

Custom logger

Implement the LoggerProvider interface to use your own logging solution:

kotlin
import com.amplitude.experiment.util.LogLevel
import com.amplitude.experiment.util.LoggerProvider

class MyCustomLogger : LoggerProvider {
    override fun verbose(msg: String) {
        // Implement verbose logging
    }

    override fun debug(msg: String) {
        // Implement debug logging
    }

    override fun info(msg: String) {
        // Implement info logging
    }

    override fun warn(msg: String) {
        // Implement warn logging
    }

    override fun error(msg: String) {
        // Implement error logging
    }
}

// Initialize with custom logger
val experiment = Experiment.initializeLocal(
    "<DEPLOYMENT_KEY>",
    LocalEvaluationConfig.builder()
        .logLevel(LogLevel.DEBUG)
        .loggerProvider(MyCustomLogger())
        .build()
)

Backward compatibility

The debug configuration field is still supported. When set to true, it overrides logLevel to DEBUG.

Was this helpful?