Environments
How to break things safely — dev, qa, and prod live under one app, each with its own database, sites, and keys.
Sarah wants to try a change to her booking flow without a real customer accidentally getting a real invoice.
There's no sandbox to sign up for and no test-mode switch to flip. Instead her app has environments — she names them whatever she likes — and each one is a fully separate estate: its own database, its own sites, its own customers, its own keys. Nothing shared between them.
Brightside Cleaning the company
└── Brightside Booking the app
├── dev test → keys start sk_test_
├── qa test → keys start sk_test_
└── prod live → keys start sk_live_Sarah's dev Portland is a real site with a real database. Bookings behave exactly as they will in prod, because it's the same code — just nobody's actual house.
Live or test
Environment names are yours; the one thing the platform cares about is the production flag. It decides two things:
| Environment is | Keys look like | Webhook URLs |
|---|---|---|
| production | sk_live_… and pk_live_… | must be https:// |
| anything else | sk_test_… and pk_test_… | http:// allowed |
Which means an sk_live_ key turning up in a test fixture or a commit is immediately
obvious. That's the point of the prefix.
Flipping the flag disables the environment's keys
You can change an environment between live and test later, but its existing keys are disabled on the spot — their prefixes would no longer tell the truth. Rotate each key to reissue it: same id, same scopes, same site grants, fresh values with honest prefixes.
What most people need
One app, two environments.
A dev environment. Point your laptop and your CI at it. Its sites are disposable; seed them, wreck them, recreate them.
A prod environment. Real customers. Real money.
Add a qa or staging one when you have something worth rehearsing — a data
migration, or a release you want to try against production-shaped data first.
Keeping them straight
Store the ids and the key together per environment, and load them from the environment rather than branching in code:
# .env.development
HYPHABASE_SECRET_KEY=sk_test_xxx
HYPHABASE_LOCATION_ID=019fb0… # dev Portland
# .env.production
HYPHABASE_SECRET_KEY=sk_live_xxx
HYPHABASE_LOCATION_ID=019aff… # real PortlandA site id from one environment means nothing to a key from another — you'll get
403, not quietly wrong data. That's the isolation doing its job, and it's also the
single most common cause of a confusing 403 while setting up. If a call fails and
both values look right, check they're from the same environment.