Environments & the Shared Catalog
What sandbox and live keep apart, what they share, and why editing a plan in sandbox can change a live customer's bill.
Quick take
- Two environments: live and sandbox
- Customer data is separated — customers, balances, subscriptions, ledger, reservations, topups, webhook events
- The catalog is NOT separated — plans, variants, billable metrics, metering rules, topup packages are shared
- Editing a plan or a price in sandbox changes it for live customers too
- The sandbox API key prefix is
qs_test_; the environment is namedsandbox
Environments & the Shared Catalog
QuotaStack gives every tenant two environments: live and sandbox. Your customer data is kept separate between them. Your catalog is not. The second half of that sentence surprises people, so this page spells out both halves.
Choosing an environment
There are three ways to pick an environment. They all point at the same two places.
With an API key. The product API decides from the key prefix.
| Prefix | Environment |
|---|---|
qs_live_... | live |
qs_test_... | sandbox |
In the dashboard. The header has a Sandbox / Live toggle. It changes which customer data you see.
With a header. Dashboard-session calls send X-Environment: sandbox or X-Environment: live.
One naming note. The sandbox API key prefix reads qs_test_, but the environment is named sandbox. They are the same place. The API, the webhook payloads, and the dashboard all use the word sandbox.
What is separate
Each of these rows is stored with the environment it belongs to. A row in one environment is invisible from the other.
| Data | What separation means |
|---|---|
| Customers | A customer created in sandbox does not exist in live. |
| Credit accounts and balances | Sandbox credits are not spendable in live. |
| Credit blocks | A block granted in sandbox never appears on a live balance. |
| Ledger entries | Each environment has its own transaction history. |
| Reservations | A sandbox hold never touches a live balance. |
| Topup purchases | A topup recorded in sandbox is a sandbox record only. |
| Subscriptions | A sandbox subscription bills nobody in live. |
| Overage events | Arrears are tracked per environment. |
| Gauge states | Seat counts and other gauges are counted per environment. |
| Webhook events | The delivery log is per environment. |
| Audit log | Each environment has its own audit trail. |
What is shared
These rows have no environment at all. There is one copy, and both environments read it.
| Catalog | Shared |
|---|---|
| Plans | Yes |
| Plan variants | Yes |
| Plan credit grants | Yes |
| Variant entitlements | Yes |
| Billable metrics | Yes |
| Metering rules | Yes |
| Topup packages | Yes |
There is no sandbox copy of a plan. There is no live copy of a metering rule. There is one of each, and a change to it is a change everywhere.
What this means in practice
These are things that will happen, not things that might.
Retire a plan in sandbox and it is retired in live. Live customers subscribed to that plan are affected right away.
Change a metering rule’s price in sandbox and live customers are charged the new price. The rule is the same row. Saving it in sandbox saves it for everyone.
Create a billable metric in sandbox and it appears in live. There is no promotion step, because there is nothing to promote.
Here is a real example. A metric named tarot_reading was created in the live environment, with a metering rule of one credit per unit. A brand-new sandbox customer was then able to reserve seven units against tarot_reading immediately, and the hold cost seven credits from the sandbox balance. The customer was sandbox. The balance was sandbox. The metric and its price came from live, because there is only one of each.
Working safely
Treat every catalog write as a production change. It does not matter which environment you are in. If you are editing a plan, a variant, a metric, a metering rule, or a topup package, you are editing live.
Give experiments their own names. Use a metric key like test_tarot_reading rather than reusing a real one. A test plan should be obviously a test plan by its name, because both environments will show it.
To try a new price, add a new metering rule. Do not edit the live one. Rules have effective dates, so a new rule can take over without touching the old one.
Check the environment badge before you edit. It tells you which customer data you are looking at. It does not protect the catalog, because there is only one catalog.
One exception worth knowing
Subscription entitlement overrides do not carry an environment of their own. They still cannot leak between environments, because an override belongs to a subscription, and subscriptions are separated. An override created against a sandbox subscription affects that sandbox subscription only.
The rule is this. Catalog rows have no environment, and they are shared. Rows that hang off a customer or a subscription follow their parent, whether or not they store the environment themselves.
Common mistakes
Don't test a price change by editing a metering rule in sandbox
Metering rules are shared. The new price applies to live customers the moment you save it. Create a new rule instead.
Don't retire or rename a plan "just to see what happens" in sandbox
Plans are shared. Retiring one in sandbox retires it in live, where real subscribers are attached to it.
Don't assume the dashboard's environment toggle protects everything
It switches which customer data you see. It does not give you a second copy of the catalog — there is only one.
Loading…