Guides
Environments & build channels
Every way your app reaches a device already has a name — Xcode, an install link, TestFlight, the App Store. Pharen maps each one to an environment for you, keeps test traffic out of your customer numbers by default, and flags the one mistake that ships silently: a test key baked into a store build.
The mapping
You never assign any of this. The environment follows the ingest key baked into each build configuration — wiring your tooling generates — and Pharen reads the channel from the build itself at runtime.
| How the build reaches a device | Environment | Channel Pharen sees | In your metrics |
|---|---|---|---|
| Run from Xcode — you, on a simulator or a cable | development | debug | Kept out of customer numbers automatically |
| Install link (ad-hoc) — teammates and test devices, many builds a day | staging | adhoc | Never mixed into production; visible to your team in staging |
| TestFlight — your beta testers, release candidates | production | testflight | In production, but excluded from customer-facing numbers by default — one filter away when you want testers included |
| App Store — your customers | production | appstore | Your customer-facing numbers; the default everywhere |
TestFlight and the App Store ship the same Release artifact, so they share the same production key on purpose: a TestFlight crash is a production-code crash you get to see before the public does. What separates testers from customers in your metrics is the channel, not the environment — customer-facing metrics default to builds that actually reached the store, so TestFlight sessions never inflate them, and a single group-by shows testers when you want them.
Two witnesses, one guard
The environment and the channel come from different places, deliberately:
- The key asserts the environment. It's compiled into the build and resolved on the server — a build cannot claim its way into your production data at runtime, and a leaked test key can be revoked without touching production.
- The build confesses its channel. At runtime the SDK reads how the binary was actually distributed — a debug build, an ad-hoc profile, a TestFlight install, the App Store — and reports it with every event.
Because the two are independent, Pharen can check them against each other. That's the guard:
Honest edges
- Web has no install channel. A browser build carries no receipt and no profile, so your key's environment is the whole story there.
- Internal vs. external TestFlight isn't knowable on-device. Both install identical builds, so Pharen reports
testflight— never which tester group. Nothing on this page promises that split, because no app can detect it. - A channel can be unknown. When a build carries no distribution signal at all, Pharen says so rather than guessing — an unknown channel never trips the guard and never masquerades as customers.