In an Expo project, what does eas submit do, and where does the uploaded build land on iOS and on Android by default?
answer
- uploads, never builds
- hosted service, works off macOS
- production submit profile by default
- iOS: App Store Connect, then TestFlight
- Android: track internal, releaseStatus completed
basics
~20 sEAS Submit is a hosted service that uploads an existing .ipa or .aab to App Store Connect or Google Play. By default an iOS build lands in TestFlight and an Android build on the internal track; nothing goes to public review automatically.
solid answer
~40 s`eas submit` builds nothing: it takes a finished binary — an EAS build chosen with `--latest` or `--id`, or a file from `--path` or `--url` — and uploads it to the store from Expo's servers. It is configured by a submit profile under the `submit` key of `eas.json`, `production` unless you pass `--profile`. On iOS the binary goes to App Store Connect and shows up in TestFlight; picking it for an App Store version and sending it to App Review is still a manual step. On Android it goes to Google Play on the profile's `track`, which defaults to `internal`, with `releaseStatus` defaulting to `completed`. So a default submission means "available to testers", not "released to the public".
code
bash · 8 lines# newest store-distribution EAS build, both platforms, production submit profile
eas submit --platform all --latest
# one specific EAS build with a named submit profile
eas submit --platform ios --id <build-id> --profile production
# a binary built outside EAS Build
eas submit --platform android --path ./app-release.aabgo deeper
Recall that eas submit uploads an existing binary and does not build it, and that the defaults land in TestFlight on iOS and the internal track on Android.
Explain how the archive source is chosen, how the submit profile is resolved from --profile, the build profile name or production, and why non-interactive runs must name both.
Show you treat submission as a gated pipeline step: defaults that reach testers only, the manual first Play upload, and App Review kept as a deliberate human decision.
Frame where automated delivery should stop: which tracks a pipeline may target unattended, and who owns promotion to production on each store.
## What EAS Submit is, and what it is not **EAS Submit** is the upload half of Expo Application Services. The `eas submit` command, part of **EAS CLI**, takes an app binary that already exists — an `.ipa` for iOS, an `.aab` (or `.apk`) for Android — and sends it to **App Store Connect** or **Google Play** on your behalf. It is a **hosted** service: the upload runs on EAS's side, which is why a developer on Windows or Linux can deliver an iOS binary even though Apple's own upload tooling runs only on macOS. It is easy to confuse with EAS Build, so be explicit in an interview: - `eas build` **produces** the binary (compiles, signs, archives). - `eas submit` **delivers** a binary that already exists. - `eas build --auto-submit` chains the two, handing each finished build to EAS Submit. Each submission is recorded on the project's submissions page on expo.dev, with a status and logs, so an upload is not a fire-and-forget terminal command. `--verbose` prints those logs in the terminal, and `--no-wait` returns as soon as the submission is queued instead of waiting for the store to accept it. That makes `eas submit` equally usable by a person at a laptop and by a pipeline step. ## Choosing which binary to upload `eas submit` needs exactly one **archive source**. Interactively it offers a list of recent builds; in `--non-interactive` mode it refuses to guess and errors unless you name one. | Flag | What it uploads | |---|---| | `--latest` | the newest **store-distribution** EAS build for the platform | | `--id <build-id>` | one specific EAS build | | `--path <file>` | a local `.ipa`, `.aab` or `.apk`, however it was built | | `--url <url>` | an archive downloadable from a URL | The flags are mutually exclusive, and `--id`, `--path` and `--url` work only with a single `--platform` (`ios` or `android`), not `all`. Note that `--latest` ignores builds made with internal distribution: a store upload needs a store-signed binary. ## Which submit profile applies Submission settings live in **submit profiles**, named objects under the `submit` key of `eas.json`, each with an `ios` and an `android` block. Resolution works like this: 1. `--profile <name>` picks that profile explicitly. 2. When you submit an EAS build without `--profile`, the CLI looks for a submit profile with the **same name as the build profile** that produced it, and falls back to `production` if there is none. 3. Otherwise it uses `production`; if even that is missing, it starts from built-in defaults and prompts for whatever is still unknown. Profiles can share settings with `extends`, the same mechanism build profiles use. ## Where an iOS submission lands The binary is uploaded to **App Store Connect**. After Apple finishes processing it, the build is available in **TestFlight**. EAS Submit does **not** submit the app for App Review and does not release it on the App Store; that remains a manual decision in App Store Connect. Two optional behaviours sit on top: - the `groups` array in the iOS submit profile (or `--groups`) names TestFlight groups the build is added to; - by default (`--auto-testflight-setup`, switched off with `--no-auto-testflight-setup`) the CLI makes a best-effort attempt to create an internal TestFlight group and invite the team's admins when the app has no groups yet. ## Where an Android submission lands The binary is uploaded to **Google Play** through the Play Developer API, authenticated with a **Google Service Account key**. It is placed on the `track` named in the submit profile, **`internal` by default**, with `releaseStatus` **`completed` by default**. Nothing reaches the production track unless the profile says `"track": "production"`. One prerequisite catches almost everyone once: Google's API cannot create the first release of a brand-new app, so the **first upload must be done manually** in the Play Console. After that, EAS Submit can take over. ## Misconceptions worth correcting - "Submit" in EAS terms means **delivered to the store's testing pipeline**, not published. - EAS Submit does not care who built the binary; `--path` accepts one built locally. - The Android defaults are deliberately conservative: internal testers, not the public. - Store listing metadata (descriptions, screenshots) is outside what `eas submit` uploads; it ships the binary.
- Why can the very first eas submit for a new Android app fail even with a valid service account key?Google Play's publishing API cannot create an app's first release, so the Expo docs require one manual upload in the Play Console before API-based submissions work. After that first upload, `eas submit` can place builds on any track the profile names.
- Does eas submit on iOS put the build in front of App Review?No. It uploads to App Store Connect and the processed build appears in TestFlight. Attaching it to an App Store version, completing the listing and submitting for review happen in App Store Connect. EAS Submit's job ends at delivery.
- What does eas submit need in --non-interactive mode that it would otherwise prompt for?An explicit archive source (`--latest`, `--id`, `--path` or `--url`), because the build picker is interactive; and on iOS an `ascAppId` in the submit profile, because looking the app up in App Store Connect needs an Apple login.
EAS Submit is a courier, not a factory: it collects a sealed parcel you already have and drops it at the store's testing dock, where someone still decides whether it goes on the shelf.
saying these in an interview costs you the question
- eas submit compiles the app and then uploads the result
- An iOS submission goes straight to App Review and the App Store
- Android submissions default to the production track
- EAS Submit only accepts binaries produced by EAS Build
- Without --profile, eas submit uses whichever submit profile is listed first