Skip to content
Gates

Offline and last-known-good

Startup

  1. Read the persisted snapshot and the installation id from storage.
  2. Resolve the runtime (from expo-application and expo-updates).
  3. ready resolves. From here flag() answers from the snapshot; before it, from the fallback.
  4. Sync in the background. Rendering never waits on this step.

What is persisted

One entry per key and environment, under @gates/state/<projectKey>/<environment>:

type PersistedState = {
  schemaVersion: 1;
  revision: number;
  projectKey: string;
  environment: string;
  flags: Record<string, FlagConfig>;
  audiences?: Record<string, ConditionConfig[]>;
  syncedAt: number;
  installationId: string;
};

A persisted snapshot is only used when it passes the shape check and its projectKey and environment match the client’s. Storage is anything with get, set and remove; AsyncStorage by default.

The installation id lives under @gates/installation-id, is minted on first launch as inst_ plus 32 hex characters, and is shared across environments so a device is the same device in preview and production.

Last-known-good

  • A network error, a timeout, a non-2xx status or a body that fails the SDK’s shape guard sets status().lastError and keeps the previous snapshot. Valid state is never overwritten by an invalid response.
  • { changed: false } marks the cached snapshot as fresh (source becomes "remote") and updates syncedAt.
  • A changed snapshot replaces flags, audiences and revision, clears the exposure dedupe, and is written back to storage.

When storage fails

If a read or write throws, the client logs a warning and keeps its state in memory for the rest of the process. Evaluation continues; the next launch starts from whatever storage still holds.

source

ValueMeaning
"none"No snapshot yet. Flags return their fallbacks. Exposure is not recorded.
"cache"Evaluating from the persisted snapshot; no successful sync yet this run.
"remote"The snapshot has been confirmed or replaced by the API this run.