skip to content

Profile Definitions

Profiles in eas.json such as development, preview and production set distribution, environment and channel per binary, and extends shares settings. Interviewers ask how one codebase yields each build.

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

explore

questions

4

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%

answer

  1. named objects under build
  2. eas build --profile, default production
  3. developmentClient: dev tools in the binary
  4. distribution: internal vs store
  5. ios.simulator: no signing needed

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.

solid answer

~50 s

`eas.json` sits next to `package.json`, and its `build` key holds named **build profiles**. `eas build:configure` generates `development`, `preview` and `production`, but the names are arbitrary. `eas build --profile preview` (short `-e`) picks one; without the flag EAS CLI uses `production`. One codebase yields different binaries because each profile changes the build's inputs: `developmentClient: true` makes a development build with expo-dev-client's tools; `distribution: "internal"` produces a directly installable build (an APK by default on Android, ad hoc or enterprise provisioning on iOS), while the default `"store"` produces a store-signed build (an AAB on Android); `ios.simulator: true` builds for the iOS Simulator with no signing; `env` and `environment` feed different variables to the app config; `channel` ties the build to an EAS Update channel. Keys under `android` or `ios` override the profile root, and `extends` shares settings.

code

json · 22 lines
json
{
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "environment": "development"
    },
    "development-simulator": {
      "extends": "development",
      "ios": { "simulator": true }
    },
    "preview": {
      "distribution": "internal",
      "environment": "preview",
      "channel": "preview"
    },
    "production": {
      "environment": "production",
      "channel": "production"
    }
  }
}

go deeper

for a junior

Recall that eas.json holds named build profiles, eas build --profile selects one, and production is the default when no profile is given.

for a middle

Explain which keys change the binary: developmentClient, distribution and its store default, ios.simulator, env, environment and channel, and how platform keys override the root.

for a senior

Show you design profiles deliberately: explicit distribution and environment on every profile, simulator variants, and awareness that channel and dev-client status are set when the binary is built, so editing eas.json never changes installed builds.

for a principal

Treat the profile set as the release contract between engineering, QA and the stores, and keep it small enough that nobody guesses which build a tester holds.

## What eas.json and a build profile are **EAS Build** is Expo's hosted service that compiles an iOS or Android binary from a project. Its configuration lives in **`eas.json`** at the project root, next to `package.json`, created the first time `eas build:configure` runs. Everything about builds sits under the `build` key, as a set of **build profiles**: named groups of settings that each describe one kind of binary. `eas build:configure` generates three profiles: ```json { "build": { "development": { "developmentClient": true, "distribution": "internal" }, "preview": { "distribution": "internal" }, "production": {} } } ``` The names carry no meaning to EAS; they could be `foo`, `bar` and `baz`. What matters is the keys inside. ## Selecting a profile - `eas build --profile preview --platform android` builds the `preview` profile for Android. - `-e` is the short form of `--profile`. - Without the flag, EAS CLI uses the profile named **`production`**; a project without one must name a profile explicitly. - The chosen profile name is exposed to the build as `EAS_BUILD_PROFILE`. ## The three conventional builds | Build | Typical keys | What testers get | |---|---|---| | Development | `developmentClient: true`, `distribution: "internal"` | A build containing expo-dev-client's developer tools, loading JS from a dev server | | Preview | `distribution: "internal"` | A production-like build installed directly by the team, not through a store | | Production | nothing, so the defaults apply | A store-ready binary, signed for App Store or Google Play | ## The keys that make the binaries differ | Key | Effect | |---|---| | `developmentClient` | `true` builds a development build that depends on `expo-dev-client` | | `distribution` | `"store"` (the default) signs for store submission; `"internal"` makes a build installable from a URL: an APK by default on Android, ad hoc or enterprise provisioning on iOS | | `ios.simulator` | `true` produces a Simulator build, which needs no Apple signing credentials | | `android.buildType` | `"apk"` or `"app-bundle"` to override the artifact type | | `env` | Plain variables set when the app config is evaluated and on the build worker | | `environment` | Which EAS environment's stored variables to load | | `channel` | The EAS Update channel baked into the build at build time | | `withoutCredentials` | Builds without signing credentials, for example an Android debug build | ## How a profile turns into a build 1. EAS CLI **resolves** the profile: it follows `extends`, merges the `android` or `ios` object over the root, and fills schema defaults such as `distribution: "store"`. 2. It **evaluates the app config** with the profile's `env` and the variables of its EAS `environment`, which is how a profile can change the app's name, identifiers or API host. 3. It works out whether **signing credentials** are needed; a Simulator build or a `withoutCredentials` build skips them. 4. It sends the project and the resolved settings to an **EAS Build worker**, which generates native folders if the project has none, installs dependencies and runs the native build for the requested artifact. Every difference between the three binaries enters through one of these steps. ## Root keys, platform keys and sharing Common keys may sit at the profile root or inside its `android` or `ios` object; the platform object wins when both set a key. That lets one profile say "internal distribution everywhere, but a Simulator build on iOS". To avoid repeating settings, a profile can declare `"extends": "<other profile>"` and inherit everything it does not override. ## A worked example: a fitness app A fitness app wants a dev client for engineers, a preview build for the coaching team, and a store build: - `development` sets `developmentClient`, internal distribution and `environment: "development"`. - `development-simulator` extends it and adds `ios.simulator: true` for engineers without a registered device. - `preview` uses internal distribution, the `preview` environment and its own `channel`. - `production` sets the `production` environment and channel and keeps store distribution. Each command, `eas build -e development`, `eas build -e preview` or `eas build -e production`, produces a different binary from the same commit. ## Common mistakes - Assuming the profile **name** does anything: a profile called `preview` with no `distribution` key is a store build. - Forgetting that `distribution` defaults to `"store"`, so a development profile without `"internal"` cannot be installed directly on a device. - Expecting a Simulator build to run on a physical iPhone; it cannot, and it is never signed. - Changing `channel` or `developmentClient` in `eas.json` and expecting existing installs to change; both are written into the binary when it is built, so only a new build picks up the edit.

  • What does EAS CLI do when eas build runs without --profile?
    It resolves the profile named `production`. If `eas.json` has no `production` profile, the command cannot resolve one and you must pass `--profile` (or `-e`) with an existing name. Relying on the default in CI is fragile; naming the profile explicitly documents which binary the job produces.
  • Why can an EAS build with ios.simulator set to true be produced without an Apple Developer account's credentials?
    A Simulator build is not code-signed for devices, so EAS skips the credentials step for it. That makes it the cheapest way to hand a standalone build to someone with a Mac, but it runs only in the iOS Simulator, never on a physical iPhone.
  • In an EAS preview profile for Android, why do testers get an APK rather than an AAB?
    Internal distribution changes Android's default build to produce an APK, which can be installed directly from a link. An AAB can only be delivered through Google Play. A profile can still override the artifact with `android.buildType`.

saying these in an interview costs you the question

  • EAS treats profiles named development and production specially by name.
  • Omitting distribution produces an internal build by default.
  • An ios.simulator build can be installed on a registered iPhone.
  • Changing a profile's channel updates builds that are already installed.
  • Platform keys under ios are ignored when the root sets the same key.
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

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