Skip to main content
The SDK keeps every config / secret / flag in an in-memory snapshot that is replaced atomically as a whole on each sync. Reads never block on the network; only the periodic background goroutine does.

When does the SDK hit the network

The atomic snapshot guarantee

The snapshot is replaced as one immutable struct value, behind a sync.RWMutex. Two goroutines reading concurrently either see the same old state or the same new state - never a mix.
This means you can iterate GetAllConfigs() or GetAllFlags() without worrying about an entry being added or removed mid-loop. The returned map is also a defensive copy.

ETag / 304

Every successful sync stores the server’s ETag. The next sync sends If-None-Match: <etag>. If nothing has changed:
…the SDK resets its SyncedAt timestamp and serves the existing snapshot. No payload transferred. When the etag changes, the new payload replaces the cache atomically.

Background sync errors

Background syncs never return errors to the caller. If the network call fails:
  1. The error is logged via Logger.Errorf(...)
  2. The existing cache continues to be served
  3. The next read after the TTL elapses retries automatically
The application is never notified - the whole point is that a transient backend hiccup doesn’t surface as a customer-facing error.

Cache lifetime

The cache lives as long as the *Client. Cancelling the context passed to NewClient does NOT release the cache; it only affects the initial sync. A *Client typically lives for the entire process - share by passing a pointer, don’t construct per-request.

Diagnostics

When you wire up a Logger, the Debugf level emits one line per sync:

Concurrency model

  • All reads are safe to call from any goroutine - internally guarded by sync.RWMutex.
  • Background sync goroutine - at most one at a time; spawned on TTL expiry.
  • SSE goroutine - at most one, started when you call go client.RunStream(ctx).
File-type secrets are materialised to os.TempDir() on every sync when the value changes. All temp files are removed when client.Close() is called.