Back to Blog

React Native Expo EAS 2026: eas build, eas init & OTA Updates

Master Expo Application Services (EAS): configure build profiles for development, preview, and production, deploy over-the-air updates with EAS Update, set up CI/CD with GitHub Actions, and manage environment variables securely.

Viprasol Tech Team
13 min read
Updated 2026

Quick answer. Expo Application Services (EAS) is the production deployment platform for React Native apps. EAS Build runs native iOS and Android builds in the cloud with no local Xcode or Android Studio setup, and EAS Update ships JavaScript fixes over-the-air in minutes, bypassing App Store review for non-native changes. Together they remove the two biggest bottlenecks in shipping React Native apps.

Expo Application Services (EAS) is the production deployment platform for React Native apps. It solves the two hardest problems in mobile development: the slow native build cycle (EAS Build) and the week-long App Store review cycle for every bug fix (EAS Update).

EAS Update โ€” Expo's over-the-air update system โ€” lets you push JavaScript and asset changes to users instantly, bypassing App Store review for anything that doesn't touch native code.


Project Setup

# Initialize EAS in an existing Expo project
npx expo install expo-updates
eas init  # Creates a project on expo.dev and writes project ID to app.json

# Install EAS CLI globally
npm install -g eas-cli
eas login
// app.json
{
  "expo": {
    "name": "MyApp",
    "slug": "myapp",
    "version": "1.0.0",
    "owner": "viprasol",
    "runtimeVersion": {
      "policy": "appVersion"  // OTA updates target matching app version
    },
    "updates": {
      "url": "https://u.expo.dev/[your-project-id]",
      "enabled": true,
      "fallbackToCacheTimeout": 30000
    },
    "android": {
      "package": "com.viprasol.myapp",
      "versionCode": 1
    },
    "ios": {
      "bundleIdentifier": "com.viprasol.myapp",
      "buildNumber": "1"
    },
    "extra": {
      "eas": {
        "projectId": "your-project-id-from-expo-dev"
      }
    }
  }
}

EAS Build Profiles

// eas.json โ€” the EAS configuration file

{
  "cli": {
    "version": ">= 12.0.0",
    "requireCommit": true  // Fail if there are uncommitted changes
  },
  "build": {
    // Development builds: includes Expo dev client, connects to Metro
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "channel": "development",
      "env": {
        "APP_ENV": "development"
      },
      "android": {
        "buildType": "apk"  // APK for direct install (faster than AAB)
      },
      "ios": {
        "simulator": false,
        "enterpriseProvisioning": "adhoc"
      }
    },

    // Preview builds: production JS, internal distribution (TestFlight/Firebase)
    "preview": {
      "distribution": "internal",
      "channel": "preview",
      "env": {
        "APP_ENV": "staging"
      },
      "android": {
        "buildType": "apk"
      },
      "ios": {
        "simulator": false
      }
    },

    // Production builds: App Store / Google Play submission
    "production": {
      "distribution": "store",
      "channel": "production",
      "env": {
        "APP_ENV": "production"
      },
      "android": {
        "buildType": "app-bundle"  // AAB required for Play Store
      },
      "ios": {
        "autoIncrement": "buildNumber"  // Auto-increment build number
      },
      "cache": {
        "disabled": false,
        "key": "production-v1"
      }
    }
  },

  "submit": {
    "production": {
      "android": {
        "serviceAccountKeyPath": "./google-play-service-account.json",
        "track": "internal",  // Start in internal testing, promote manually
        "releaseStatus": "draft"
      },
      "ios": {
        "appleId": "your@apple-developer-email.com",
        "ascAppId": "1234567890",  // App Store Connect app ID
        "appleTeamId": "TEAMID"
      }
    }
  }
}

๐ŸŒ Looking for a Dev Team That Actually Delivers?

Most agencies sell you a project manager and assign juniors. Viprasol is different โ€” senior engineers only, direct Slack access, and a 5.0โ˜… Upwork record across 1000+ projects.

  • React, Next.js, Node.js, TypeScript โ€” production-grade stack
  • Fixed-price contracts โ€” no surprise invoices
  • Full source code ownership from day one
  • 90-day post-launch support included

Environment Variables in EAS

Environment variables in EAS require a specific pattern to be embedded in the JS bundle:

// src/config/env.ts
// Use expo-constants for runtime config, process.env for build-time

import Constants from "expo-constants";

// Values available at runtime (from app.json extra or EAS)
interface AppConfig {
  apiUrl: string;
  sentryDsn: string;
  analyticsKey: string;
  environment: "development" | "staging" | "production";
}

function getConfig(): AppConfig {
  const env = process.env.APP_ENV as AppConfig["environment"] ?? "development";

  return {
    // process.env is inlined at build time by Metro bundler
    apiUrl: process.env.API_URL ?? "http://localhost:3000",
    sentryDsn: process.env.SENTRY_DSN ?? "",
    analyticsKey: process.env.ANALYTICS_KEY ?? "",
    environment: env,
  };
}

export const config = getConfig();
# Store secrets in EAS (encrypted, not in eas.json)
eas secret:create --scope project --name API_URL --value "https://api.viprasol.com"
eas secret:create --scope project --name SENTRY_DSN --value "https://..."
eas secret:create --scope project --name ANALYTICS_KEY --value "..."

# Secrets are automatically available as process.env during builds
# List all secrets (values hidden)
eas secret:list

EAS Update: Over-the-Air Updates

// src/hooks/useOTAUpdate.ts
// Check for and apply updates when app comes to foreground

import { useEffect } from "react";
import * as Updates from "expo-updates";
import { AppState, AppStateStatus, Alert } from "react-native";

export function useOTAUpdate() {
  useEffect(() => {
    // Don't run in development (Expo Go / dev client handles this differently)
    if (__DEV__) return;

    const subscription = AppState.addEventListener(
      "change",
      async (nextAppState: AppStateStatus) => {
        if (nextAppState !== "active") return;

        try {
          const update = await Updates.checkForUpdateAsync();

          if (!update.isAvailable) return;

          // Download silently in background
          await Updates.fetchUpdateAsync();

          // For critical updates: reload immediately
          // For non-critical: prompt user
          Alert.alert(
            "Update Available",
            "A new version of the app is ready. Restart to apply.",
            [
              { text: "Later", style: "cancel" },
              {
                text: "Restart Now",
                onPress: async () => {
                  await Updates.reloadAsync();
                },
              },
            ]
          );
        } catch (error) {
          // Update check failed โ€” non-fatal, app continues to work
          console.warn("OTA update check failed:", error);
        }
      }
    );

    return () => subscription.remove();
  }, []);
}

Update Channels and Rollout Strategy

# Channels map to build profiles in eas.json
# Publish an update to the preview channel
eas update --channel preview --message "Fix crash on settings screen"

# Publish to production with rollout percentage
eas update --channel production --message "v1.2.1 - Performance improvements" \
  --rollout-percentage 10  # Start with 10% of users

# Monitor the rollout, then expand
eas update:view   # Check error rates on the update
eas update --channel production --message "v1.2.1" --rollout-percentage 100

# Roll back if needed
eas update:republish --channel production --group <previous-update-group-id>

react-native - React Native Expo EAS 2026: eas build, eas init & OTA Updates

๐Ÿš€ Senior Engineers. No Junior Handoffs. Ever.

You get the senior developer, not a project manager who relays your requirements to someone you never meet. Every Viprasol project has a senior lead from kickoff to launch.

  • MVPs in 4โ€“8 weeks, full platforms in 3โ€“5 months
  • Lighthouse 90+ performance scores standard
  • Works across US, UK, AU timezones
  • Free 30-min architecture review, no commitment

CI/CD with GitHub Actions

# .github/workflows/eas-build.yml
name: EAS Build and Update

on:
  push:
    branches:
      - main         # Triggers preview build + OTA update
      - production   # Triggers production build + submit
  pull_request:
    branches: [main]

env:
  EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}  # Authenticate with expo.dev

jobs:
  # Run on every PR: type check + tests
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          cache: "npm"
      - run: npm ci
      - run: npx tsc --noEmit
      - run: npm test -- --watchAll=false

  # Push to main: publish OTA update to preview channel
  update-preview:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          cache: "npm"
      - run: npm ci
      - name: Install EAS CLI
        run: npm install -g eas-cli
      - name: Publish OTA update to preview
        run: |
          eas update \
            --channel preview \
            --message "Auto-update from commit ${{ github.sha }}" \
            --non-interactive

  # Push to production branch: build + submit
  build-production:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/production' && github.event_name == 'push'
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          cache: "npm"
      - run: npm ci
      - name: Install EAS CLI
        run: npm install -g eas-cli
      - name: Build for production
        run: |
          eas build \
            --platform all \
            --profile production \
            --non-interactive \
            --wait
      - name: Submit to stores
        run: |
          eas submit \
            --platform all \
            --profile production \
            --non-interactive \
            --latest  # Submit the build we just created

Runtime Version Strategy

The runtime version controls which OTA updates are compatible with which builds:

// Option 1: appVersion policy (recommended for most teams)
// OTA updates only target devices running the matching app version
// Update 1.2.x only reaches users on app version 1.2.x
{
  "runtimeVersion": { "policy": "appVersion" }
}

// Option 2: nativeVersion policy
// OTA updates target matching native code hash
// More granular โ€” update reaches users with identical native code
{
  "runtimeVersion": { "policy": "nativeVersion" }
}

// Option 3: Explicit string (full control)
// You manually bump when native code changes
{
  "runtimeVersion": "1.2"
}

The rule: bump the runtime version when you change native code (new native module, updated expo version, modified android/ or ios/ directories). OTA updates don't require a runtime version bump.


Cost Comparison

ApproachBuild TimeOTA UpdatesMonthly Cost
Expo Go (development)Instant (no build)N/AFree
EAS Build free tier15โ€“30 min1,000 updatesFree
EAS Build production tier15โ€“30 minUnlimited$99/month
EAS EnterprisePriority queueUnlimitedCustom
Self-hosted (Turtle CLI)20โ€“40 minN/A~$50/month infra

Additional Resources


Video Tutorial: Expo EAS Build & Deployment

This 15-minute video walks through:

  • Setting up EAS Build profiles for development, preview, and production
  • Configuring OTA updates with EAS Update for instant deployments
  • Automating builds and submissions with GitHub Actions
  • Managing environment variables and secrets securely

Frequently Asked Questions

Q: What is Expo Application Services (EAS)?

A: Expo Application Services (EAS) is the production deployment platform for React Native apps. It includes EAS Build (native compilation in the cloud) and EAS Update (over-the-air deployments). EAS eliminates the need for local Xcode/Android Studio setup and enables instant app updates without App Store review.

Q: How do I set up EAS Update for instant deployments?

A: Install the expo-updates package, run eas init to configure your project on expo.dev, add the project ID to your app.json, and use eas update to push JavaScript changes instantly. Updates bypass App Store review for non-native code changes.

Q: What's the difference between EAS Build and native build?

A: EAS Build compiles native code in the cloud, eliminating the need for local Xcode or Android Studio installation. Native builds require local toolchain setup and take longer. EAS Build is significantly faster for CI/CD pipelines and distributed teams.

Q: How do I configure build profiles in EAS?

A: Define build profiles in your eas.json file for development, preview, and production environments. Each profile specifies native code versions, environment variables, and distribution settings (internal vs. app store).

Q: Can I use EAS with GitHub Actions for CI/CD?

A: Yes. Install eas-cli in your GitHub Actions workflow, authenticate with EXPO_TOKEN, and use eas build or eas update commands. This enables fully automated build and deployment pipelines on push to main or production branches.


Our Capabilities

EAS dramatically reduces the operational overhead of mobile app deployment. Our React Native development team sets up EAS Build profiles, configures OTA update channels for staged rollouts, integrates EAS into CI/CD pipelines, and manages App Store/Play Store submissions โ€” so your team ships features instead of managing mobile build infrastructure.

Related Reading:

Mobile app development โ†’ | Start a project โ†’

Expo EAS Pricing 2026: What eas Expo Plans Actually Cost

Planning a budget around Expo EAS pricing in 2026 means looking past the headline tiers. The free plan gives you a limited number of EAS Build minutes and queued builds each month, which is fine for early prototyping. Paid plans add concurrent builds, faster build queues, larger artifact storage, and higher OTA update bandwidth through EAS Update. As your eas Expo usage scales, the variables that move your bill are build concurrency, monthly build volume, and update delivery, not the base subscription alone. Self-hosted runners can offset Build minutes if you have the infrastructure. At Viprasol, our senior engineers help you model real EAS Build and EAS Update costs against your release cadence, then architect pipelines so you pay for throughput you genuinely need, with full ownership of every config.

Expo EAS & eas.json FAQ

What is EAS in Expo? EAS (Expo Application Services) is Expo's cloud build and submit service. EAS Build compiles your iOS/Android binaries in the cloud, EAS Submit uploads them to the App Store / Play Store, and EAS Update ships over-the-air JavaScript updates.

What is the eas.json file? eas.json is the configuration file at your project root that defines build profiles (development, preview, production) - environment variables, build types, credentials source, and submit settings for each profile.

How do I configure build profiles in eas.json? Each profile under the "build" key sets options like distribution, channel, and environment; "submit" profiles hold store credentials. Run the EAS CLI against a named profile to build or submit.

Building a React Native app with Expo? Talk to our mobile team.

react-nativeexpomobilecicdtypescript
Share this article:

About the Author

V

Viprasol Tech Team

Custom Software Development Specialists

The Viprasol Tech team specialises in algorithmic trading software, AI agent systems, and SaaS development. With 1000+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement.

MT4/MT5 EA DevelopmentAI Agent SystemsSaaS DevelopmentAlgorithmic Trading

Need a Modern Web Application?

From landing pages to complex SaaS platforms โ€” we build it all with Next.js and React.

Free consultation โ€ข No commitment โ€ข Response within 24 hours

Viprasol ยท Web Development

Need a custom web application built?

We build React and Next.js web applications with Lighthouse โ‰ฅ90 scores, mobile-first design, and full source code ownership. Senior engineers only โ€” from architecture through deployment.