Release Channels vs Environments: They're Not the Same Thing
How to model OTA release tracks, app-defined runtime context, native compatibility, and Bundle Drop infrastructure without collapsing them into one environment label.
A release channel and an environment can both carry names such as development, beta, or production. That overlap is convenient, but it does not make them the same concept.
In Bundle Drop, a channel is a named OTA release track inside a project. An app checks one channel, an upload targets one channel, and a compatible bundle can be promoted from one channel to another. A customer app environment is application-defined runtime context passed during BundleDrop.init(). It can describe where or how that app build operates, but it does not select an OTA release by itself and does not grant access to one.
There are two more identities that are often folded into the same word: runtimeVersion, which is the per-platform native compatibility boundary, and Bundle Drop's internal platform environment, where ENV_NAME distinguishes PROD from STAG. Keeping all four axes separate makes release behavior easier to predict.
One installation can carry four independent coordinates
Release track
Channel: beta
Chooses the named OTA stream this installation follows.
Native compatibility
Runtime: ios "4.2-native-1"
Limits delivery to bundles compatible with the installed binary.
Application context
appEnvironment: "production"
Carries an app-defined value; compatibility paths may call it environment.
Bundle Drop infrastructure
ENV_NAME: PROD
Selects the platform deployment and is not customer release configuration.
Four axes, four questions
Use each value to answer one narrow question:
| Axis | Question it answers | Example |
|---|---|---|
| Channel | Which OTA release track does this app process check? | beta |
| Runtime version | Which native interface can this bundle safely execute against? | 5.4-ios-2 |
| App environment | What application context does this running build report? | staging |
| Bundle Drop platform environment | Which Bundle Drop infrastructure deployment is running? | PROD |
These values may correlate in a particular release pipeline, but none should silently substitute for another. A production app environment can check a beta channel for an employee dogfood build. A production channel can contain compatible bundles for several runtime versions while users adopt a new store binary. Bundle Drop's STAG infrastructure can be used to validate platform changes without turning STAG into a customer channel or app environment.
Channels route OTA releases
Every Bundle Drop project starts with a develop channel, and teams can create other named tracks. The app chooses its active track at startup:
BundleDrop.init({
environment: "staging",
channelName: "beta",
policy: "on-next-launch",
});
The upload command names the same track explicitly:
npx bundle-drop upload ios --channel beta
npx bundle-drop upload android --channel beta
The channel must already exist. Upload does not create it. When an installation checks for an update, Bundle Drop resolves within that project, channel, platform, and runtime-version lane, then applies publishing, targeting, and rollout rules.
After those identities establish the lane, managed publishing, targeting, rollout percentage, and fallthrough determine which release wins inside it.
This makes a channel a release-routing mechanism. Moving an app process from beta to production changes the release track it checks. Changing its app environment from staging to production does not perform that switch.
The full lifecycle is documented under Channels, and the supported upload inputs are listed under Uploading.
App environments describe application context
The environment option passed to BundleDrop.init() is required customer-app context. Teams define its vocabulary. Common values are development, staging, and production, but a product might instead use internal, preview, or region-specific labels.
Within the product model, this is the appEnvironment concept. Some compatibility API payloads and storage records still use the field name environment; that naming does not turn it into infrastructure configuration. Bundle Drop records the value with update checks, install reporting, and analytics so activity can be understood in the app's own context.
It is not an authorization boundary. A device does not gain permission to an OTA bundle because it reports environment: "production", and changing the string is not a safe way to protect privileged code or data. Product authorization remains the responsibility of the application and its backend. If a release needs audience rules, use defined user properties and the documented targeted rollout properties, while remembering that rollout targeting is still release eligibility rather than product authorization.
Treat app-environment values as durable telemetry dimensions. Keep spelling and casing consistent across builds; otherwise production, prod, and Production become separate labels that make reporting harder to interpret.
Runtime versions enforce compatibility
runtimeVersion is independent of both channel and environment. It identifies the native capability set available to an OTA bundle on a specific platform. Bundle Drop delivers a bundle only when its platform runtime version exactly matches the installed binary's runtime version.
For example:
module.exports = {
defaultChannel: "production",
runtimeVersion: {
ios: "5.4-ios-2",
android: "5.4-android-1",
},
};
An iOS bundle for 5.4-ios-2 can be present on develop, beta, and production. Promotion changes where the artifact is available; it does not change the artifact's runtime compatibility. Likewise, renaming an app environment cannot make a bundle compatible with a different native binary.
Changing a channel or app-environment label cannot make a bundle compatible with a different native binary. For the full per-platform compatibility-line model and literal-versus-Expo authority options, see Runtime versions: the compatibility boundary for React Native OTA updates. The configuration reference lives in Runtime Version.
PROD and STAG belong to Bundle Drop infrastructure
Bundle Drop itself has platform and administration deployments. Their ENV_NAME values are normalized around PROD and STAG. This setting controls which Bundle Drop infrastructure deployment a service or administration surface belongs to.
It is not a customer-controlled release track. Do not create logic that maps ENV_NAME=PROD to the customer's production channel, or normalize a customer's app-defined staging value into STAG. Those strings live in different namespaces and have different owners:
- platform operators choose
PRODorSTAGfor Bundle Drop services; - application teams define their own app-environment values;
- project maintainers create channels inside a project;
- native release engineers define runtime versions per platform.
This boundary matters in tooling and documentation. A dashboard connected to Bundle Drop STAG may still manage a project containing a channel literally named production. The identical-looking label describes customer release intent, not the infrastructure serving the dashboard.
Model development, beta, and production explicitly
A useful release setup models each concern on its own, even when the names happen to align.
| Build or audience | App environment | Channel | Runtime version |
|---|---|---|---|
| Local developer build | development | develop | platform-specific dev line |
| Employee or QA build | staging | beta | same as production only if natively compatible |
| Store build | production | production | current iOS or Android production line |
This table is a convention, not a Bundle Drop requirement. Consider a store-signed employee build that uses real production APIs but should receive updates before the public. Its values could be:
BundleDrop.init({
environment: "production",
channelName: "beta",
policy: "on-next-launch",
});
That combination is coherent: the app operates in the product's production context while following the beta OTA track. If it is built from the same native inputs as the public app, both can also share a runtime version. If the employee build includes an extra native diagnostics module, it needs a separate runtime compatibility line even if both builds call the same production APIs.
Another team may use one app environment and several channels, or several app environments that all check one channel. Choose combinations deliberately rather than enforcing a one-to-one mapping that the runtime does not require.
Promote artifacts, not assumptions
Channels support a verification pipeline without rebuilding or re-uploading identical content. A typical flow is:
- Upload an iOS or Android bundle to
develop. - Validate that exact hash on compatible internal installations.
- Promote the bundle to
betafor a wider test group. - Promote the same bundle to
productionwhen it passes release checks.
Promotion adds the existing bundle to the target channel as-is. Its hash, platform, runtime version, and bundle version remain unchanged. The source channel retains it, and rollback or removal is channel-scoped. On the target channel, version ordering still matters: an artifact older than the target lane's latest bundle is added but does not automatically become the served update.
A channel designated as the project's production channel also has production retention behavior. That designation affects how long newly uploaded or promoted bundles are retained; it does not convert the channel into an app environment. See Production Channels for those lifecycle rules.
Promotion works best when the pipeline preserves identity. Validate the exact hash, promote it forward, and avoid rebuilding nominally identical source at each stage. Rebuilding creates another artifact and weakens the evidence gathered in the previous channel.
Avoid overloaded naming and hidden coupling
Several patterns create ambiguity:
- Using runtime versions as stages. Values such as
betaandproductiondo not describe native compatibility. They force unrelated compatibility changes into release routing. - Using app environment to choose updates implicitly. The update track is
channelName. Keep that choice visible in startup configuration or an intentional channel-switching flow. - Treating a production channel as authorization. Anyone who can legitimately run a configured client still needs application-level permissions for protected capabilities and data.
- Mapping customer values to
PRODandSTAG. Internal platform environment normalization must not rewrite customer app context. - Creating a channel per native build. A channel can hold multiple runtime lines. Create a new channel for a distinct release audience or workflow, not every runtime bump.
- Encoding every user segment as a channel. If users share a release track but a rollout needs a temporary audience gate, typed rollout properties are usually the clearer mechanism.
Prefer short, stable, lowercase channel names such as develop, beta, and production. Document what audience each channel serves, who may publish or promote into it, and whether managed publishing or production retention is enabled. Separately document the app-environment vocabulary and which backend configuration each value selects.
Review releases as a tuple
Before publishing, review the complete release identity rather than asking whether a bundle is "for production":
project + channel + platform + runtimeVersion + bundle hash
Then record the app environment as execution context and verify any rollout eligibility rules separately. A release checklist should answer:
- Which channel will installations check?
- Which iOS or Android runtime line can execute the artifact?
- Which exact bundle hash was validated and promoted?
- What does the app-defined environment mean for API configuration and telemetry?
- Are audience controls release targeting, or are they product permissions that belong elsewhere?
Once those answers are explicit, familiar labels stop carrying hidden behavior. Channels route releases, runtime versions protect native compatibility, app environments describe the customer's runtime context, and PROD or STAG identifies Bundle Drop's own infrastructure. The names may resemble one another; the contracts should not.