Skip to content

JVM SDK

Server-side capture for the JVM — Kotlin-first and comfortable from Java, with events, identity, super properties and feature flags.

azfive-jvm is the JVM server SDK — Kotlin-first, comfortable from Java. Events, identity, super properties, and feature flags / experiments, under the shared behavioral spec. Requires Java 17+; single runtime dependency (kotlinx-serialization-json).

Install

The package resolves through JitPack:

repositories {
    maven("https://jitpack.io")
}

dependencies {
    implementation("com.github.az-five:azfive-jvm:v0.1.0")
}

Use a secret API key with the events:write scope — server SDKs post to /api/v1/events, where public tokens are rejected.

Initialize

import com.azfive.capture.AzFiveClient
import com.azfive.capture.AzFiveConfig

val azfive = AzFiveClient(
    AzFiveConfig(
        apiKey = "azfive_…",
        host = "https://app.az-five.com",
    )
)

From Java, use the builder — the client is AutoCloseable:

import com.azfive.capture.AzFiveClient;
import com.azfive.capture.AzFiveConfig;
import java.util.Map;

AzFiveConfig config = AzFiveConfig.builder("azfive_…", "https://app.az-five.com")
        .batchSize(20)
        .gzip(true)
        .build();

try (AzFiveClient azfive = new AzFiveClient(config)) {
    azfive.capture("invoice_paid", Map.of("amount", 99), "user-42");
}

A blank apiKey or host fails at construction — the only place this SDK raises. Delivery and flag failures are always silent.

Capture events

Pass the user per call, server-SDK style:

azfive.capture("invoice_paid", mapOf("amount" to 99), distinctId = "user-42")

// Super properties — merged into every event
azfive.register(mapOf("deployment" to "eu-1"))

Identify & person properties

azfive.identify("user-42", set = mapOf("plan" to "pro"))
azfive.alias("legacy-77")
azfive.people.set(mapOf("favorite_color" to "teal"))

identify with a new id emits az.identify (carrying $anonymous_id) and reloads flags; with the already-identified id it emits a property update only. Opt-out survives reset().

Feature flags

Flag methods take the distinct_id first; decide responses are cached per id (60 s TTL, LRU 10,000):

val variant = azfive.getFlag("user-42", "exp-checkout")        // Boolean | String | null
if (azfive.isFlagEnabled("user-42", "new-billing")) { /* … */ }
val payload = azfive.getFlagPayload("user-42", "exp-checkout") // no exposure event
azfive.reloadFlags("user-42")                                  // bust one id's cache

getFlag and isFlagEnabled capture an az.flag_called exposure automatically (deduped on distinctId:flag:value, bounded LRU 50,000). getFlagPayload never does. Network failures serve stale values or an empty document — never an exception.

Flush & shutdown

A daemon worker flushes every flushIntervalMs and whenever the queue reaches batchSize:

azfive.flush()   // force-send queued events
azfive.close()   // flush + stop worker (also runs via JVM shutdown hook)

In Java, try-with-resources covers this: the client flushes on close.

Reference

AzFiveConfig

ParameterDefaultNotes
apiKeyrequiredazfive_… secret key or azfive_pub_… public token
hostrequiredAZ-Five deployment base URL
project"default"Target project slug
batchSize10Queue length that triggers a flush
flushIntervalMs5000Background flush period
maxQueueSize1000Queue bound; oldest events dropped on overflow
gzipfalseContent-Encoding: gzip on event POSTs
optOutfalseStart opted out of capturing
disableDecidefalseDisable the /v1/decide flag client
startFlushWorkertrueDisable the background worker (tests)

Every parameter is also available on the Java Builder.

API

capture · identify · alias · reset · register / registerOnce / unregister · people.set / people.setOnce · getFlag / isFlagEnabled / getFlagPayload / reloadFlags · flush · close.

Behavior notes

  • Endpoints: secret keys post to /api/v1/events; public tokens (azfive_pub_…) to /api/v1/events/ingest.
  • Server runtime: identity is in-memory only, there are no sessions (getSessionId() returns ""), and events are stamped with $device_type: "Server".
  • Failed batches — 429 included — re-queue at the front and retry on the next flush tick, bounded keeping the newest events.
  • Custom event names: anything except the reserved az. prefix, ≤ 200 characters; properties ≤ 64 KiB serialized.