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?
answer
- never let EAS generate a new keystore
- credentials.json first, then upload
- eas credentials, Android, credentials.json menu
- compare SHA-1 or SHA-256 fingerprints
- CI run first = random keystore
basics
~20 sDescribe 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.
solid answer
~50 sPlay must keep seeing uploads signed by the **same upload key**, so EAS must never generate one for this app. Before the first Android `eas build`, I write a git-ignored `credentials.json` with the keystore's `keystorePath`, `keystorePassword`, `keyAlias` and `keyPassword`, run `eas credentials -p android`, pick the build profile, and choose **Upload credentials from credentials.json to EAS**. That step is interactive; if EAS already holds a keystore it asks before overwriting and backs the old one up. Then I compare the SHA-1 or SHA-256 fingerprint `eas credentials` prints with the upload certificate in Play Console, build with the default remote source, and delete local copies apart from an offline backup. The classic failure is a first build from CI: non-interactively, EAS silently generates a random keystore and Play rejects the bundle. If the key is truly lost, Play App Signing allows an upload key reset.
code
json · 10 lines{
"android": {
"keystore": {
"keystorePath": "../secure/upload-keystore.jks",
"keystorePassword": "KEYSTORE_PASSWORD",
"keyAlias": "upload",
"keyPassword": "KEY_PASSWORD"
}
}
}go deeper
Recall that Google Play only accepts updates signed with the app's registered upload key, so EAS must use the existing keystore, not a new one.
Walk through credentials.json fields, the eas credentials upload menu and the interactive prompt that otherwise offers to generate a keystore.
Show the operational guardrails: fingerprint verification, a human-run first build, the non-interactive generation trap, backups and download permissions.
Decide who is custodian of the upload key after migration, and how a lost or leaked key is handled, before the first EAS build runs.
## The situation A team has a React Native app on Google Play, built until now with Gradle on a laptop or a CI runner. It is moving to EAS Build with **managed (remote) credentials**. The app uses **Play App Signing**, so Google holds the app signing key, and the team holds an **upload keystore**: a `.jks` file, a key alias and two passwords. Every future bundle must be signed with that upload key, or Play Console rejects the upload. The danger is that EAS is happy to create a brand-new keystore the first time it builds an application ID it has no credentials for. The migration is about making sure that never happens. ## The procedure 1. **Locate the real upload keystore** and confirm it is the one Play expects: compare its certificate fingerprint with the upload key certificate shown in Play Console. 2. **Describe it in `credentials.json`** at the project root and git-ignore both the JSON and the keystore: - `android.keystore.keystorePath` - `android.keystore.keystorePassword` - `android.keystore.keyAlias` - `android.keystore.keyPassword` 3. **Upload it before any Android build.** Run `eas credentials -p android`, select the build profile whose application ID this is, open **credentials.json: Upload/Download credentials between EAS servers and your local json**, and choose **Upload credentials from credentials.json to EAS**. The step only runs interactively. If a keystore is already configured for that application ID, EAS CLI asks whether to overwrite it and first saves a backup of the existing one. 4. **Verify on EAS.** `eas credentials` prints the stored keystore with its MD5, SHA-1 and SHA-256 fingerprints; they must match Play Console's upload certificate. 5. **Build and upload** a release with the default `credentialsSource: "remote"`. A successful Play upload is the final proof. 6. **Clean up.** Remove `credentials.json` and the keystore from developer machines and CI secrets, keep one offline, access-controlled backup, and record who can download it from EAS. ## Why the order matters When EAS Build needs an Android keystore and none is configured: | Mode | What EAS CLI does | |---|---| | Interactive (`eas build` in a terminal) | Asks whether you want to provide your own keystore or let EAS generate one | | Non-interactive (`--non-interactive`, typical in CI) | Generates a new random keystore without asking | So the most common migration failure is a CI job that runs the first EAS build. It succeeds, produces a correctly signed bundle, and Play rejects it because the upload key is different. The fix is the same procedure: upload the real keystore, confirm the overwrite (the generated one is backed up), and rebuild. The generated key never reached Play, so nothing is lost. ## Variations - **Several keystores.** EAS can hold more than one keystore per application ID, with one marked as the default. A profile can pick a non-default one with `keystoreName`, which is only allowed with remote credentials. `eas credentials` offers **Change default keystore** for switching. - **Staying local for a while.** A team can set `credentialsSource: "local"` and build from `credentials.json` until it trusts the setup, then upload. Local credentials are uploaded per build and discarded afterwards. - **The key is lost.** With Play App Signing, the team can generate a new upload keystore, export its certificate to PEM with `keytool -export -rfc`, and ask Google Play support to register it as the new upload key. The app signing key Google holds is unaffected, so installed apps keep updating normally once the reset is accepted. ## Checking the migration worked - The EAS dashboard and `eas credentials` show exactly one keystore for the application ID, marked as the default, with the expected fingerprints. - The first bundle built by EAS is accepted by Play Console on an internal testing track before any production release depends on it. - CI jobs run with remote credentials and no longer receive the keystore or its passwords as secrets. ## What a senior candidate is expected to add - Check fingerprints, not file names: several `.jks` files with plausible names often exist in old projects. - Treat the first EAS Android build as a **gated** step, run by a person, not by CI. - Limit who can download credentials from EAS through project roles, since any download is a new copy of the key. - Keep the upload key separate from the service account key used for store submission; they are different credentials with different blast radii.
- What happens if an Android app's first EAS build runs in CI with --non-interactive and no keystore on EAS?EAS CLI generates a new random keystore without asking and signs with it. The build succeeds, but Google Play rejects the bundle because it is not signed with the registered upload key. Upload the real keystore with `eas credentials`, confirm the overwrite, and rebuild; the generated keystore never reached Play.
- Does replacing a lost upload key through Play App Signing affect users who already installed the app?No. Under Play App Signing, Google re-signs every release with the app signing key it holds, which does not change. The upload key only authenticates uploads to Play, so a reset changes which key the team signs uploads with; installed apps keep receiving updates signed by Google's key.
saying these in an interview costs you the question
- Let EAS generate a fresh keystore; Play accepts any valid signature.
- Running the first EAS build from CI is safe because nothing prompts.
- The keystore file name is enough to confirm it is the upload key.
- Uploading to EAS is irreversible, so keep credentialsSource local forever.
- A lost upload key means the app can never be updated, even with Play App Signing.