> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prodbreak.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Point a staging app at a sandbox

> Use a long-lived instance as a staging-like environment, not just a test fixture.

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

```bash theme={null}
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](/interception)), 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`](/guides/seed-history) you'd use in a test, once, right after the instance comes up:

```ts theme={null}
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 `POST`s 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](/guides/seed-history) for the full semantics.

<Tip>
  **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.
</Tip>

## Wall-clock mode is the right default here

A staging sandbox runs in [wall-clock mode](/concepts/clock#two-modes): 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](/guides/deterministic-ci).)

## Know the durability trade-off

<Warning>
  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.
</Warning>

## 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.

<Note>
  **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.
</Note>
