The same sandbox that backs your tests can run long-lived — point a real app at it like a staging
environment, but controllable and free of the real vendor.
Spin one up
prod-break run deck
# ▸ url=http://localhost:8801 key=pbw_3f9a…
Point your app’s config at that URL and key (the one base-URL change), and use it
like any staging backend. The control surface is identical to the testing path — seed data, arm
faults, fire world events, advance the clock — just over a longer-lived world.
Seed a baseline at setup
A fresh sandbox boots empty. For a staging-style environment you usually want a known baseline —
some accounts, a few customers, whatever your app expects to already exist. Use the same
seed you’d use in a test, once, right after the instance comes up:
import { prodbreak } from "@prod-break/sdk";
const sandbox = await prodbreak.connect({ url: PRODBREAK_URL, key: PRODBREAK_KEY });
// stand up the baseline this environment should always have
await sandbox.seed("customers", [
{ id: "cus_demo_alice", email: "alice@example.com" },
{ id: "cus_demo_bob", email: "bob@example.com" },
]);
await sandbox.seed("accounts", [
{ id: "acct_demo_1", customer_id: "cus_demo_alice", balance: 0 },
]);
It’s a silent insert of history — no webhooks fire, nothing runs. From here your app drives the
world live (its real POSTs run the lifecycle on top of the seeded baseline). Same rules as in tests:
you supply format-correct ids, and ProdBreak never invents the surrounding history — see
Seed history for the full semantics.
Keep the seed in a script — the recipe is durable, the world is not. Because the store is
in-memory (below), a restart wipes the seeded state. Treat your seed script as the source of truth and
re-run it on boot, exactly like a beforeEach for your staging environment. A first-class “boot with a
named fixture” (point the CLI at a seed file and it loads on startup) is on the roadmap.
Wall-clock mode is the right default here
A staging sandbox runs in wall-clock mode: time advances on its own, so
scheduled events fire over real time like a real environment. (For tests you’d collapse durations
instead — see Deterministic CI.)
Know the durability trade-off
The MVP store is in-memory. A restart or redeploy of the instance wipes the world — fine for
ephemeral CI (everything is reset() anyway), but a real consideration for a staging instance you’ve
seeded and left running. Treat seeded staging state as reproducible-on-demand (keep your seed script),
not as durable data. A SQLite-backed store for restart survivability is on the roadmap.
Hosted vs local
The SDK is distribution-agnostic — hosted vs local changes only the base URL
(https://acme.sandbox.prod-break.io vs http://localhost:8801). Start local with the CLI; a hosted
option (one instance per customer, handed a URL + key) is the planned first distribution.
Treat the world key as sensitive in staging. Webhook signing secrets are derived from it, so a
leaked key exposes those secrets. For ephemeral CI worlds this is a non-issue; for a shared staging
instance, handle the key like any credential.