Intro
Expo backup and restore should move you from a detected problem to a verified result. Start by identifying the installed version, deployment topology, prerequisites, and the exact component being inspected. This guide is for developers, DevOps consultants, and technical startup teams who need to protect their mobile build pipeline.
It connects backup, restore, disaster recovery, rollback, and validation to commands, expected output, failure signals, and recovery decisions. The goal is operational safety: observe before changing, limit the blast radius, use placeholders instead of secrets, verify the result, and document how to recover if the expected state is not reached.
Version and Environment Inventory
Before any backup or restore operation, capture the exact state of your Expo environment. This prevents version mismatches and ensures you can reproduce the setup.
How to Check Your Expo Version and Environment
Run this read-only command to see the global Expo CLI version:
expo --version
Expected output example:
6.3.10
For project-specific SDK and dependency versions, inspect package.json and app.json:
node -e "console.log(require('./package.json').dependencies.expo)"
node -e "console.log(require('./app.json').expo.sdkVersion)"
Example result:
~50.0.0
50.0.0
Prerequisites
- Node.js 18 LTS or newer.
- Expo CLI installed globally (
npm install -g expo-cli) or usenpx expofor project-level commands. - Git repository with a clean working tree (
git status --porcelainshould return empty). - Access to your version control platform (GitHub, GitLab, Bitbucket) and any CI/CD system.
Blast Radius
Version checks are read-only and have no impact on running services. They are safe to run anytime.
Verification
Confirm the version matches the one documented in your project's lockfile (yarn.lock or package-lock.json) and your CI runner.
Safe Configuration Path
Follow a structured path when changing Expo configuration files such as app.json, eas.json, or metro.config.js. A single typo can break your build or leak secrets.
Step 1: Observe Current Configuration
View the current app.json without modifying:
cat app.json
This shows the current settings. Note any environment variables referenced with process.env.
Step 2: Make a Scoped Change with a Backup
Always create a backup before editing:
cp app.json app.json.bak.$(date +%Y%m%d%H%M%S)
Then edit using a version-controlled method. For example, to add an environment variable for your API URL in eas.json:
{
"build": {
"production": {
"env": {
"API_URL": "https://api.example.com"
}
}
}
}
Replace the URL with a placeholder in documentation; never commit real secrets.
Step 3: Verify the Change
After editing, validate the JSON syntax:
node -e "JSON.parse(require('fs').readFileSync('app.json', 'utf8')); console.log('Valid JSON')"
Expected output:
Valid JSON
Then run a prebuild dry run to see if the configuration resolves:
npx expo prebuild --no-install
This generates native projects in memory (or in a temp directory) and reports errors without installing dependencies.
Recovery Path
If the change breaks the build, restore the backup:
cp app.json.bak.$(date +%Y%m%d%H%M%S) app.json
Better yet, use git to revert to the last known good commit:
git checkout -- app.json
Verification and Diagnostics
After any backup or restore, you must verify the project is operational. Here are practical checks.
Check Expo Doctor
Expo provides a built-in diagnostic tool:
npx expo-doctor
Expected output when healthy:
✔ Check Expo config (app.json/App.config.js) schema
✔ Check that packages match versions required by installed Expo SDK
✔ Check for legacy global CLI installed locally
✔ Check that native modules do not use incompatible support packages
✔ Check that the project does not depend on incompatible web packages
✔ Check package.json for common issues
If any check fails, the output shows a specific error with remediation steps.
Validate the JavaScript Bundle
Export the bundle to ensure it compiles without errors:
npx expo export --platform all
A successful export creates a dist folder with index.html, metadata.json, and bundle files. Check the exit code:
echo $?
Expected output: 0
If the export fails, read the error message; it often points to a missing module or syntax error.
Test the Restored State Locally
Run the app in development mode:
npx expo start
Then use the Expo Go app or an emulator to load the project. Monitor the terminal for bundling progress and any red error screens.
Failure Modes and Recovery
Backups and restores can fail in several ways. Anticipate them and have a recovery plan.
Common Failure Modes
- Incomplete Backup: You backed up only part of the project (e.g.,
src/but forgotapp.jsonorpackage.json).
- Why it happens: Manual copy or selective commit.
- Recovery: Recreate the missing files from version control if available; otherwise, reconstruct from memory and reconfigure secrets.
- Secret Leak in Backup: You committed a
.envfile or hardcoded a token.
- Why it happens: Lack of
.gitignorerules or careless copy. - Recovery: Immediately rotate the leaked credentials, remove the file from history (e.g., using
git filter-repoor BFG), and add.envto.gitignore.
- Version Mismatch After Restore: Dependencies or Expo SDK versions differ from the original environment.
- Why it happens: Restoring on a system with different global packages or not using a lockfile.
- Recovery: Delete
node_modulesand reinstall withnpm cioryarn install --frozen-lockfile. Usenpx expo install --fixto align package versions with the SDK.
- Corrupted Cache: Metro bundler cache or
.expofolder leads to stale builds.
- Why it happens: Interrupted builds or switching between branches.
- Recovery: Clear caches with
npx expo start -cand delete.expofolder. For extreme cases, deletenode_modulesandpackage-lock.jsonand reinstall.
Recovery Verification
After any recovery, run the verification suite again: expo-doctor, expo export, and a local start check.
Operations Checklist
Use this checklist before every backup or restore operation. Assign each item to a single accountable owner (for teams) and revisit it after each major release or monthly.
| # | Checklist Item | Owner | Frequency |
|---|---|---|---|
| 1 | Confirm Expo SDK and CLI versions match documentation (run expo --version and check package.json) | Priya Shah, Engineering Lead | Every backup |
| 2 | Ensure no uncommitted changes: git status --porcelain is empty | Marcus Chen, DevOps Engineer | Every backup |
| 3 | Backup app.json, eas.json, package.json, metro.config.js, and any environment files (excluding secrets) to a secure location | Priya Shah | Every backup |
| 4 | Encrypt and store secrets in a password manager or secret manager (e.g., Hashicorp Vault) | Marcus Chen | Every backup |
| 5 | Verify backup integrity: list files and compare checksums | Automated script (owned by Marcus Chen) | Every backup |
| 6 | Test restore in a clean clone or container | QA Engineer, Aisha Patel | Monthly or after major dependency change |
| 7 | Review disaster recovery plan and update contact list | Priya Shah | Quarterly |
Common Pitfalls and How to Avoid Them
Beyond failure modes, these mistakes are common:
- Relying on a single local backup: Disk failure or laptop loss can destroy everything. Use offsite or cloud storage with versioning (e.g., S3, GCS, GitHub releases).
- Ignoring
eas.jsonand other configs in backups: Developers often back up source code but miss build profiles, which can lead to failed EAS builds. - Not testing restore regularly: A backup is only good if you can restore it. Schedule periodic restore drills.
- Storing secrets in plain text inside the project: Use environment variables and
.envfiles that are gitignored, or use Expo's secret management in EAS. - Changing configuration without a rollback plan: Always keep a copy of the last known good configuration or use Git branches.
Conclusion
Expo backup and restore is useful only when each recommendation is version-scoped, observable, and reversible. Copying a command without checking prerequisites and expected output is not an operations procedure.
As a next step, choose one low-risk verification (e.g., run npx expo-doctor), record the current state, run the documented check, compare the result with the expected signal, and review dependencies such as React Native, Android, and your CI/CD system.
A reliable technical workflow makes failure visible, protects sensitive values, limits changes to the intended resource, and defines recovery verification before an incident forces the decision.