Shipeasy

Offline & snapshots

Build a fully offline client from a captured snapshot — real evaluation, zero network. For CI, tests, and air-gapped runtimes.

Production readyOn this page · 3 min readUpdated · June 19, 2026Works with · @shipeasy/sdk · server

Sometimes you want real flag evaluation with no network at all — a CI job, a deterministic test, an air-gapped runtime. A snapshot is just the two SDK wire bodies captured to disk; the client evaluates the real rules against it.

The snapshot shape

A snapshot is the bodies of GET /sdk/flags and GET /sdk/experiments:

// snapshot.json
{
  "flags":       /* body of GET /sdk/flags */,
  "experiments": /* body of GET /sdk/experiments */
}

Load it

fromFile / fromSnapshot build an Engine — the heavyweight client — from the captured blob. (Everyday flag reads use configure + new Client(user); here you build an isolated, offline Engine.)

import { Engine } from "@shipeasy/sdk/server";

// from a file (Node only — reads with node:fs)
const engine = Engine.fromFile("./snapshot.json");

// or from a parsed object you already hold (works anywhere)
const engine = Engine.fromSnapshot({ flags, experiments });

engine.getFlag("new_checkout", { user_id: "u1" });

Evaluations run the real eval against the snapshot. init() / initOnce() / track() are no-ops, and override* setters still apply on top — handy for forcing a specific case in a test.

fromFile is Node-only

fromFile reads the file with node:fs. In a browser, an edge runtime, or anywhere without a filesystem, fetch or import the JSON yourself and pass it to fromSnapshot.

When to use it

  • CI / tests — deterministic evaluation with no live dependency.
  • Air-gapped or offline runtimes — ship a snapshot alongside the build.
  • Reproducing a bug — capture production rules once and replay them locally.

For seeding individual values without a snapshot, use forTesting() + overrides instead.

Was this page helpful?
✎ Edit this page

On this page