skip to content

EAS Build & Submit

EAS Build turns eas.json profiles into signed iOS and Android binaries in the cloud, and EAS Submit uploads them to the stores. Interviewers probe profiles and credentials, where pipelines break.

part ofExpo (React Native)overview, primer and where to startread it →
on this pageshow

explore

questions

17

Which signing credentials does an EAS build need for Android and for iOS, and who holds them by default?

level: juniorimportance: must knowfreq 45%

answer

  1. Android: one keystore, alias, two passwords
  2. iOS: certificate plus per-app profile
  3. certificate is account-wide
  4. credentialsSource defaults to remote
  5. EAS generates on first build

basics

~20 s

Android builds are signed with a keystore (key alias and passwords); iOS builds need a distribution certificate plus an app-specific provisioning profile. By default credentialsSource is remote: EAS generates them on the first eas build and stores them encrypted on its servers.

solid answer

~50 s

On **Android**, EAS signs the APK or AAB with a **keystore**: a private key under a key alias, protected by a keystore password and a key password. With Play App Signing that key is the **upload key**, and Google re-signs the app with its own app signing key. On **iOS**, a device build needs a **distribution certificate**, which belongs to the Apple Developer account and can serve all its apps, and a **provisioning profile**, which is app-specific and binds the bundle identifier to that certificate (plus a device list for ad hoc). Push keys are managed alongside but do not sign builds. `credentialsSource` defaults to `"remote"`: on the first `eas build`, EAS CLI offers to generate what is missing (signing in to Apple for iOS), stores it encrypted on EAS servers, and reuses it for later builds and teammates. Simulator builds need none of this.

go deeper

for a junior

Recall the pieces: a keystore on Android, a distribution certificate plus provisioning profile on iOS, and that EAS generates and stores them by default.

for a middle

Explain scope and lifetime: the account-wide certificate, the app-specific profile that expires yearly, ad hoc device lists, and the upload key under Play App Signing.

for a senior

Show you know which loss hurts: iOS certificates and profiles can be regenerated freely, while losing the Android key means a support-driven upload key reset at best and no more updates at worst.

for a principal

Decide who in the organization owns the Apple team and the Play upload key, and whether EAS or an internal system is the custodian of record.

## Why builds are signed at all Both mobile platforms refuse to install or update an app that is not **code-signed**: the signature proves who produced the binary and that it was not altered. EAS Build can produce unsigned artifacts, for example iOS Simulator builds, but anything installed on a device or submitted to a store must be signed. EAS calls the files and secrets involved **credentials**. ## Android: the keystore An Android release is signed with a key stored in a **keystore** file. Four values describe it, the same four `credentials.json` uses: - `keystorePath`, the `.jks` or `.keystore` file; - `keystorePassword`, which unlocks the file; - `keyAlias`, which names the key inside it; - `keyPassword`, which unlocks that key. Google Play checks that every update is signed consistently with earlier releases. With **Play App Signing**, which is the default for new apps, the key EAS holds is the **upload key**: Google verifies the upload and re-signs the app with an app signing key it keeps itself. From EAS's point of view nothing changes: it signs with whatever keystore is associated with the application ID. ## iOS: certificate plus profile | Credential | Scope | Used for | Notes | |---|---|---|---| | Distribution certificate | the Apple Developer account, shared by all its apps | signing | a `.p12` with a password | | Provisioning profile | one bundle identifier | signing | ties the app ID to the certificate; ad hoc profiles also list device UDIDs; expires after 12 months | | Push notification key | the account | run time, not signing | managed from `eas credentials`, but a build does not need it to sign | A store build uses an App Store profile; an **internal** distribution build uses an ad hoc or enterprise profile, so only registered devices can install an ad hoc build. Each app extension target, such as a widget or share extension, has its own bundle identifier and so its own profile. ## Who holds them by default A build profile's `credentialsSource` decides where EAS Build gets credentials, and it defaults to **`"remote"`**: 1. On the first `eas build` for a platform, EAS CLI detects that nothing is configured and offers to set it up. 2. For Android it can generate a new keystore or accept one you provide. 3. For iOS it asks you to sign in with an Apple Developer Program account, then creates or reuses a distribution certificate and creates a provisioning profile. 4. The results are stored on EAS servers, encrypted at rest and with a key management service, and decrypted only in memory on the build workers. 5. Later builds reuse them, and teammates with the right project permissions can build iOS apps without access to the Apple team. The alternative, `credentialsSource: "local"`, reads everything from a git-ignored `credentials.json` for each build. ## What does not need credentials - A build profile with `ios.simulator: true` produces a Simulator build, which EAS does not sign. - `withoutCredentials: true` builds without signing, for example an Android debug build. - A development build installed on a physical device **does** need signing, typically ad hoc on iOS. ## Inspecting and managing them `eas credentials` (optionally `-p android` or `-p ios`) is the interactive manager: it shows what is configured, including keystore fingerprints, and lets you download, replace or delete credentials. Deleting there removes them from EAS only; Apple-side certificates and profiles must be revoked in the Apple Developer portal. ## A quick decision table | Build | Signing needed | What EAS uses | |---|---|---| | Android store build (AAB) | Yes | the upload keystore | | Android internal build (APK) | Yes | a keystore, reused if the application ID already has one | | iOS App Store build | Yes | distribution certificate plus App Store profile | | iOS internal build | Yes | distribution certificate plus ad hoc or enterprise profile | | iOS Simulator build | No | nothing | ## Common misconceptions - The iOS distribution certificate is not per app; a single certificate can sign every app of the team. - A provisioning profile expiring does not break the app already on the store; it only blocks new builds until a new profile is created. - Losing the Android upload key is recoverable through Google Play support when Play App Signing is on; without it, updates signed with a different key are rejected.

  • Why can a teammate start an EAS iOS build without being a member of the Apple Developer team?
    With remote credentials, the distribution certificate and provisioning profile are already stored on EAS servers. A teammate with sufficient permissions on the Expo project can start a build that uses them; Apple access is only needed when credentials must be created or regenerated.
  • Why does an EAS internal distribution build for iOS install only on some iPhones?
    Internal distribution on iOS uses ad hoc provisioning (or enterprise, with that program). An ad hoc profile lists the UDIDs of allowed devices, so only devices registered when the profile was generated can install it. Adding one means registering it and producing a new profile, by rebuilding or re-signing.

The iOS distribution certificate is your personal signature, valid on everything you sign; a provisioning profile is a per-app permit saying which signature may ship which app to which devices. The Android keystore is a wax seal pressed into every release: the store checks updates against it, so losing it means asking the store to register a new seal, or never updating the app again.

saying these in an interview costs you the question

  • Each iOS app needs its own distribution certificate.
  • An expired provisioning profile disables the app already on the App Store.
  • The Apple push key is required to sign every iOS build.
  • credentialsSource defaults to local, so a credentials.json is required.
  • Simulator builds need a distribution certificate like device builds.
open as a page

In EAS Build, what is a build profile in eas.json, and how does one Expo codebase yield development, preview and production builds?

level: juniorimportance: must knowfreq 50%

basics

~20 s

An EAS build profile is a named object under build in eas.json describing one kind of binary; eas build --profile <name> selects it. Keys like developmentClient, distribution, ios.simulator, env and channel make each profile's binary different.

open as a page

In an Expo project, what does eas submit do, and where does the uploaded build land on iOS and on Android by default?

level: juniorimportance: must knowfreq 55%

basics

~20 s

EAS 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.

open as a page

In EAS Build, what is the difference between the remote and local cli.appVersionSource in eas.json, and how does autoIncrement behave under each?

level: middleimportance: must knowfreq 50%

basics

~20 s

With remote, EAS servers store versionCode and buildNumber and inject them at build time; autoIncrement bumps the server counter. With local, the project files are the truth and autoIncrement edits app.json, which you must commit.

open as a page

With EAS Build, how do you make every production iOS build go to a TestFlight tester group automatically, and which submit profile does --auto-submit use?

level: middleimportance: must knowfreq 45%

basics

~20 s

Run eas build --profile production --auto-submit: each finished build is handed to EAS Submit using the submit profile with the same name as the build profile. Put ascAppId and a groups array in that profile's ios block.

open as a page

What does eas build --local do in an Expo project, and how does it differ from a build on EAS's cloud servers?

level: juniorimportance: should knowfreq 35%

basics

~20 s

eas build --local runs the same build process EAS runs in the cloud, but on your own macOS or Linux machine. It is for debugging cloud failures or keeping builds in-house; it needs your own toolchain and skips caching.

open as a page

In EAS Build, how do remote (managed) credentials and local credentials from credentials.json differ, and when would you choose local?

level: middleimportance: should knowfreq 35%

basics

~20 s

Remote credentials are generated or uploaded once and stored encrypted on EAS servers; local credentials are read from a git-ignored credentials.json on every build, uploaded with the job and discarded afterwards. A profile picks with credentialsSource.

open as a page

With EAS Workflows, how do you build and submit a budgeting app on every push to main, and how does the submit job get the build?

level: middleimportance: should knowfreq 40%

basics

~10 s

A YAML file in .eas/workflows triggers on push to main, runs a build job (type: build) per platform, then a submit job (type: submit) that needs it and reads its build_id output.

open as a page

In an EAS build profile, how do the env and environment fields differ, and which value wins when both define a variable?

level: middleimportance: should knowfreq 30%

basics

~20 s

env holds literal variables written in eas.json; environment names an EAS environment whose stored variables are loaded. When both define a name, the profile's env value wins and EAS CLI warns. Without environment, EAS picks production, development or preview from the profile.

open as a page

In eas.json, how does extends merge a child EAS build profile with its parent, and what can the child silently inherit?

level: middleimportance: should knowfreq 32%

basics

~20 s

With extends, EAS CLI resolves the parent first, then overlays the child: child keys replace the parent's, while env, android and ios are merged key by key. Anything the child does not override, such as developmentClient or channel, is inherited.

open as a page

In an EAS Submit Android profile, what do track, releaseStatus and rollout control, and which combinations does eas.json validation reject?

level: middleimportance: should knowfreq 35%

basics

~20 s

track names the Google Play track (default internal), releaseStatus sets how the release is created (completed, draft, inProgress or halted; default completed), and rollout is a 0-1 fraction that is required with inProgress and rejected otherwise.

open as a page

An app already on Google Play moves to EAS Build; how do you bring its existing upload key into EAS managed credentials without breaking updates?

level: seniorimportance: should knowfreq 25%

basics

~20 s

Describe the existing upload keystore in credentials.json, upload it with eas credentials before any Android eas build, and check its fingerprint against the upload certificate in Play Console. Otherwise EAS generates a new keystore that Play rejects.

open as a page

In an EAS project, what happens to live apps and future builds when an iOS distribution certificate, a provisioning profile or the Android upload key is revoked, expires or leaks?

level: seniorimportance: should knowfreq 22%

basics

~20 s

iOS distribution certificates and provisioning profiles are used only at build time, so expiry or revocation never breaks live apps; they are regenerated with eas credentials. Replacing a lost or leaked Android upload key needs a Play upload key reset.

open as a page

A budgeting app already on both stores is moving to EAS builds on every merge to main; how do you switch it to remote build numbers without a rejected upload?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Seed EAS's counter with the last build number each store accepted using eas build:version:set, set appVersionSource to remote and autoIncrement on the production profile, remove build numbers from app config, and replace a nativeVersion runtime policy.

open as a page

How would you design EAS development, preview and production build profiles for a fitness app so all three install side by side and reach the right backend?

level: seniorimportance: should knowfreq 24%

basics

~20 s

Give each profile an APP_VARIANT in env so the app config assigns a distinct bundle identifier and package, set distribution and environment explicitly per profile so each loads its own backend variables, and give preview and production separate channels.

open as a page

An eas submit step works on your laptop but fails in a non-interactive CI job; what must the EAS submit profile and environment provide for iOS and Android?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Every prompt must be answered in advance: EXPO_TOKEN for the Expo account, an explicit archive source, and on iOS an ascAppId plus an App Store Connect API key; on Android a Google Service Account key and one earlier manual upload.

open as a page

In EAS Build, what do the eas-build-pre-install and eas-build-on-success scripts in package.json do, and when does each run?

level: middleimportance: nice to knowfreq 20%

basics

~10 s

They are package.json scripts EAS Build runs at fixed points: eas-build-pre-install before the JavaScript dependencies are installed, and eas-build-on-success at the end of a build that succeeded. Custom builds do not run them automatically.

open as a page