Release Channels & Branches
Staging → production promotion with EAS Update - a cookbook for channels, branches, and the linear promotion flow that keeps preview QA aligned with production behavior.
Search across all documentation pages
Staging → production promotion with EAS Update - a cookbook for channels, branches, and the linear promotion flow that keeps preview QA aligned with production behavior.
Quick-reference recipe card - copy-paste ready.
// eas.json - channel per build profile
{
"build": {
"preview": { "distribution": "internal", "channel": "preview" },
"production": { "channel": "production" }
}
}# Publish to preview branch (soak)
eas update --branch preview --channel preview --environment preview \
--message "feat: checkout validation fix"
# After QA sign-off - publish same commit to production channel
eas update --branch production --channel production --environment production \
--message "promote: checkout validation fix"# Inspect what each channel serves
eas channel:view production
eas update:list --branch production --limit 5When to reach for this:
development → preview → production flow.When to avoid:
jane-dev) - use preview builds + branch updates instead.End-to-end staging → preview → production promotion with channel/branch tables and CI gate.
Step 1 - Document the channel map
<!-- docs/release-channels.md -->
| Channel | Binary profile | Audience | Who may publish |
|--------------|----------------|-----------------|----------------------|
| development | development | Engineers | Any dev (local) |
| preview | preview | QA + stakeholders | Tech lead on-call |
| staging | preview* | Pre-prod soak | Release manager |
| production | production | Store users | CI tag only |
* staging uses preview profile binary with `expo-channel-name: staging` header override if neededStep 2 - Wire branches to channels
# One-time: ensure channels point at intended branches
eas channel:create preview
eas channel:create production
eas channel:edit preview --branch preview
eas channel:edit production --branch productionStep 3 - Feature work on preview
git checkout -b fix/checkout-validation
# ... JS changes only (OTA-safe) ...
eas update --branch preview --channel preview --environment preview \
--message "fix: card validation regex"Step 4 - QA on preview binary
# QA installs eas build --profile preview artifact
# Maestro smoke + manual payment path on physical device
eas update:list --branch preview --limit 3Step 5 - Promote to production (CI preferred)
# .github/workflows/eas-update-production.yml (excerpt)
name: Promote OTA to production
on:
workflow_dispatch:
inputs:
message:
required: true
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- run: eas update --branch production --channel production \
--environment production \
--message "${{ github.event.inputs.message }}"What this demonstrates:
requestHeaderseas update:list, GitHub Actions logs)eas update --branch feature-x → writes bundle to branch "feature-x"
eas channel:edit preview --branch feature-x → preview channel now serves feature-x
App checks channel "preview" → receives head of branch feature-x| Concept | Role |
|---|---|
| Channel | Named endpoint devices query (expo-channel-name header) |
| Branch | Git-like line of updates; holds bundle history |
| Build profile | Embeds default channel in binary via eas.json |
eas update --channel production publishes to the branch currently linked to production--branch when promoting so history stays traceableeas channel:view <name> shows branch mapping and current update IDdevelopment → preview (QA) → staging (optional soak) → production
↑ ↑ ↑ ↑
engineer internal build 24–48h soak CI tag only# Trunk-based: publish from main to preview branch
git checkout main
eas update --branch preview --channel preview --environment preview
# GitFlow: publish from release/x.y to staging branch
git checkout release/2.4
eas update --branch staging --channel staging --environment stagingproduction publish from unmerged feature branchesWhen preview and production should run the same bundle artifact:
# Option A - cherry-pick commit and publish to production branch
git checkout main
git cherry-pick <preview-commit-sha>
eas update --branch production --channel production --environment production \
--message "promote: <ticket-id>"
# Option B - channel redirect (advanced; use with care)
eas channel:edit production --branch preview
# Follow immediately with branch split if preview continues divergingpreview header never sees production updates. Fix: Rebuild or match publish channel to embedded header..env on production publish - Wrong API host in OTA bundle. Fix: eas update --environment production always.projectId, channel, and bundle ID per variant.| Alternative | Use When | Don't Use When |
|---|---|---|
| Branch per Git feature | Parallel QA of features | Too many stale branches |
Single main branch for all channels | Small team, linear flow | Need parallel soaks |
eas channel:rollout | Gradual production exposure | Need full soak on preview first |
| Store-only releases | Native every sprint | Weekly JS-only fixes |
Minimum: development, preview, production. Add staging when revenue paths need 48h soak. Avoid per-person channels.
Technically yes, but it erases promotion audit trails. Prefer separate branches and promote via explicit publish or documented channel edit.
eas channel:view production
eas update:view <update-id>--channel publishes to the branch linked to that channel. --branch targets a branch directly. Use both for clarity during promotion.
Strongly recommended. Break-glass laptop publish needs second approver, eas update:list screenshot, and postmortem requirement.
requestHeaders wiringStack versions: This page was written for React 19.2.3, React Native 0.86.0, and Expo SDK 57 (
expo~57.0.4).
Reviewed by Chris St. John·Last updated Jul 16, 2026