Skip to content

Java Feature Flags Quickstart

This guide gets you from zero to evaluating a feature flag in a Java application. The SDK requires Java 11+.

  • A Featureflip account with at least one feature flag created
  • An SDK key from your environment settings
  • Java 11+ and Gradle or Maven
build.gradle.kts
dependencies {
implementation("io.featureflip:featureflip-java:2.0.0")
}
<dependency>
<groupId>io.featureflip</groupId>
<artifactId>featureflip-java</artifactId>
<version>2.0.0</version>
</dependency>
import io.featureflip.client.FeatureflipClient;
import io.featureflip.client.EvaluationContext;
// Recommended: get a singleton client using the SDK key.
try (FeatureflipClient client = FeatureflipClient.get("your-sdk-key")) {
EvaluationContext context = EvaluationContext.builder("user-123").build();
boolean showFeature = client.boolVariation("new-feature", context, false);
if (showFeature) {
// show the new feature
}
}

FeatureflipClient.get() returns a handle to a process-wide singleton client. Calling it multiple times with the same SDK key returns handles that share one underlying client — no duplicate streaming connections. Call waitForInitialization() to block until the initial flag fetch completes.

If you need custom configuration, use the builder (the deduplication still applies):

import io.featureflip.client.FeatureflipClient;
import io.featureflip.client.FeatureFlagConfig;
FeatureFlagConfig config = FeatureFlagConfig.builder()
.baseUrl("https://eval.featureflip.io")
.streaming(true)
.initTimeout(Duration.ofSeconds(30))
.build();
FeatureflipClient client = FeatureflipClient.get("your-sdk-key", config);
client.waitForInitialization();

waitForInitialization() blocks until the fetch completes or the init timeout expires (10 seconds by default). It throws FeatureFlagInitializationException if initialization fails.

import io.featureflip.client.EvaluationContext;
EvaluationContext context = EvaluationContext.builder("user-123").build();
boolean showBanner = client.boolVariation("new-banner", context, false);
if (showBanner) {
System.out.println("Showing the new banner");
} else {
System.out.println("Using the default experience");
}

The third argument is the default value returned when the flag is not found or evaluation fails.

Other variation methods are available for different value types:

String color = client.stringVariation("banner-color", context, "blue");
int limit = client.intVariation("rate-limit", context, 100);
double ratio = client.doubleVariation("rollout-ratio", context, 0.5);

You can attach custom attributes to the evaluation context for use in targeting rules:

EvaluationContext context = EvaluationContext.builder("user-123")
.set("plan", "pro")
.set("country", "US")
.build();

The client implements AutoCloseable. Use try-with-resources to ensure it flushes pending analytics events and stops background connections:

try (FeatureflipClient client = FeatureflipClient.get("your-sdk-key")) {
client.waitForInitialization();
boolean result = client.boolVariation("new-banner",
EvaluationContext.builder("user-123").build(), false);
System.out.println("Flag value: " + result);
}

If you are managing the client lifetime manually, call client.close() explicitly.

The Java SDK is a server-side SDK that evaluates flags locally in your JVM process. On initialization, it fetches the full flag configuration from the Featureflip evaluation API. An SSE streaming connection keeps the configuration up to date in near-real-time — polling every 30 seconds is available as a fallback. Because evaluation happens locally, boolVariation() and other variation calls return immediately with no network latency.

If the SDK loses its connection to the evaluation API, it continues using the last known configuration. Your application keeps working with the most recent flag values until the connection is restored.

FeatureFlagInitializationException on startup

This means the SDK could not fetch the initial configuration within the timeout (10 seconds by default). Verify your SDK key matches the target environment and that your application can reach eval.featureflip.io over HTTPS. In containerized environments, DNS resolution delays are a common cause — check that your /etc/resolv.conf is configured correctly.

Flags return default values after successful init

Flag keys are case-sensitive. Verify the key string matches the dashboard exactly. Also confirm the flag is enabled in the environment matching your SDK key — flags are independently toggled per environment.

NoClassDefFoundError or ClassNotFoundException at runtime

This typically means the SDK dependency was not included in your packaged artifact. If you use Gradle’s implementation scope, the dependency is included in JAR builds but verify it is on the runtime classpath. For Maven, ensure the scope is compile (the default), not provided.