Release Architecture

Expo release work has three separate paths: build, submit, and update.

The Pieces

PieceWhat it doesCommon mistake
EAS BuildCreates signed Android/iOS binariesTreating a dev server run as release proof
EAS SubmitUploads binaries to Play Console or App Store ConnectAssuming submit handles metadata, screenshots, privacy, or review
EAS UpdatePublishes compatible JavaScript/assets OTAShipping native or permission changes OTA
Runtime versionCompatibility boundary between binary and updateReusing one runtime after native changes
ChannelBuild-time pointer to update streamConfusing store tracks with update channels
BranchUpdate stream where update groups are publishedPublishing production fixes to the wrong branch
Store track/TestFlightStore distribution surfaceTreating TestFlight/internal as production

Default Profile Ladder

{
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal"
    },
    "preview": {
      "distribution": "internal",
      "channel": "preview",
      "android": { "buildType": "apk" }
    },
    "production": {
      "channel": "production",
      "autoIncrement": true,
      "android": { "buildType": "app-bundle" }
    }
  },
  "submit": {
    "production": {
      "android": { "track": "production" },
      "ios": {}
    }
  }
}

Keep project-specific credential paths out of committed examples unless the files are gitignored and documented.

Release Rule

If the change affects native code, app config, permissions, SDK version, runtime version, package ID, bundle ID, signing, or store policy, it belongs in a new binary first. OTA can follow after the new binary is available.