---
title: 'Build fast, no matter what: how Expo is optimizing for speed (and how you can, too)'
authors: Keith Kurak
published: May 13, 2026
categories: Product, Development, React Native
tags: Build speed, Expo Services
---

You need speed. 

Whether you’re a student shipping your first app between classes, an engineer sneaking in progress on your side project over lunch, or part of an enterprise team responsible for millions of users, the constraint is the same. You don’t have time to wait on builds. You need feedback instantly. You need to ship while the idea is still fresh. 

When builds are slow, momentum dies. When builds are fast, you stay in flow and that’s when great products actually get made. 

Our aim is to provide the fastest builds to you no matter what plan you are on._ _To deliver on this promise we are taking steps to address the unprecedented demand for Expo, mac hardware, and scaling to meet the needs of enterprise engineers and vibe coders alike.

Mac Minis are a hot commodity for aspiring AI automators using OpenClaw, especially the configurations with extra RAM (which itself was already a scarce resource). If you've ever taken a peek at our [build server configuration page](https://docs.expo.dev/build-reference/infrastructure/#ios-build-server-configurations), you know iOS builds run on well-equipped M4 Mac Minis. With the perfect storm of long lead times for Mac Mini shipments worldwide, a surge of app development across the world from vibe coders, indie devs, local business, and enterprises, it’s only natural to wonder how this might affect Expo’s Build and Workflows queues.

**Here is what we are doing to speed up builds and increase our infra:**

- First, we've recently added dozens of new M4 Pro and Max Mac Minis to our fleet, we are racking more as we speak and have more ordered and en route.
- We’re taking several measures to make each build faster, which means more builds for everyone.
   - We recently deployed compiler-level caching for SDK 54 and 55 projects to improve the speed of your fastlane and gradlew step by up to 30%.
   - We’re deploying Gradle caching to improve Android build performance.
   - We’re adding prebuilt binaries for commonly-used packages like `react-native-reanimated` and `react-native-screens` to practically eliminate the time that it takes to build those artifacts.
   - SDK 56 ships [prebuilt XCFrameworks](https://docs.expo.dev/guides/prebuilt-expo-modules/) for our most complex Expo modules on iOS, to speed up your iOS builds.

Our vision is to give every builder the chance to make something real. The first time you use Expo and a build finishes **fast** you feel it. Then it happens again, and at some point you stop thinking about builds entirely. You trust that things will work and they’ll be fast. That’s the bar for us: infrastructure you don’t have to think about so you can focus on building something beautiful.

The same bar applies to our tools. Our developer tools should help you make the most of each build and make it easier to tap into the capabilities of your own hardware.

## Building less often with fingerprint-based workflows

What’s even faster than building on an EAS M4 Max large worker with ccache and prebuilt React Native binaries enabled? How about not building at all?

Even if you don’t need [Expo’s OTA Updates](https://expo.dev/solutions/eas-ota-updates) to deliver bug fixes over-the-air to your production app, it’s a great fit for making your preview app feedback loop as tight as possible. Most apps don’t need a full rebuild on every code change, since most code changes are JavaScript only. Instead, ship an update to rebuild only the JavaScript and let your existing app install download the new code.

Run `eas update:configure` to setup your app to use EAS Update and rebuild. You can use a [dynamic app config](https://docs.expo.dev/workflow/configuration/#dynamic-configuration) to enable updates just for your preview app (set `updates.enabled` to `false` in this case).

You could then update your app manually by running `eas update --channel preview` whenever you know you didn’t change any native code or dependencies. Or, you can set this up as an [EAS workflow ](https://expo.dev/services/workflows)that [runs automatically on commit and selectively either builds or updates based on the sampling of a native fingerprint](https://expo.dev/blog/accelerating-continuous-integration-with-fingerprint-repack-in-eas-workflows), a hash that only changes when your native code changes.

Connect your Expo project to Github, and then add this workflow to the **.eas/workflows** folder:

```markup
name: Build or update preview on main push, based on fingerprint

on:
  # Trigger on pushes to main branch
  push:
    branches: [main]

jobs:
  fingerprint:
    environment: preview
    type: fingerprint

  ios_get_build:
    needs: [fingerprint]
    type: get-build
    params:
      fingerprint_hash: ${{ needs.fingerprint.outputs.ios_fingerprint_hash }}
      platform: ios
      profile: preview

  ios_update:
    needs: [ios_get_build]
    if: ${{ needs.ios_get_build.outputs.build_id }}
    type: update
    params:
      channel: preview
      platform: ios

  ios_build:
    needs: [ios_get_build]
    if: ${{ !needs.ios_get_build.outputs.build_id }}
    type: build
    params:
      platform: ios
      profile: preview
      
  # add the same steps for Android to handle those builds/updates, as well!
```

[See the docs for a full example of this workflow](https://docs.expo.dev/eas/workflows/examples/deploy-to-production/).

Adding EAS Update to your app and using it to update your code whenever possible is a great way to get the most mileage out of each build.

## Building locally for development and testing

Running `npx expo start` to spin up a local development server for running your app on Expo Go or a development build might be the most popular thing to do with the [Expo CLI](https://docs.expo.dev/more/expo-cli/), but the Expo CLI can also [build and run your app directly on a simulator or device](https://docs.expo.dev/more/expo-cli/) if you need to in a pinch.

### Getting started

When building locally, the Expo CLI taps into your existing Android Studio or Xcode installation to access native development tools. Setting up these tools just right can be a little tricky, so we’ve provided a [local build guide](https://docs.expo.dev/guides/local-app-overview/) with instructions to setup known-good configurations for [Android](https://docs.expo.dev/get-started/set-up-your-environment/?platform=android&device=physical&mode=development-build&buildEnv=local#set-up-an-android-device-with-a-development-build) and [iOS](https://docs.expo.dev/get-started/set-up-your-environment/?platform=ios&device=physical&mode=development-build&buildEnv=local#set-up-an-ios-device-with-a-development-build) builds. Note that iOS builds will require a Mac computer.

### Local development builds

Once the native tools are installed, you can do the following to build and run your app on an emulator or simulator:

`npx expo run:android`

or

`npx expo run:ios`

This makes a debug build of your app and starts a local development server (i.e., what `npx expo start` does). So, not only were you able to make a build locally, but it’s ready to go with live-reloading as you edit your JavaScript code.

The first time you run this command, it will also run `npx expo prebuild` to generate your native android and iOS folders. If you add packages with native code or make changes to app.json, you will generally want to run `npx expo prebuild --clean` to regenerate these folders and then run `npx expo run:android|ios` to build again. This approximates what EAS would do each time it builds your app.

This setup gets even better if you install `expo-dev-client`. This is the package that will [turn any debug build into a development build](https://docs.expo.dev/develop/development-builds/introduction/), allowing you to open any development server URL. Once the development build is installed on your emulator or simulator, you don’t need to keep rebuilding it as long as your native runtime stays the same. Just run `npx expo start` and press `a` to open on Android and `i` to open on iOS.

### Release builds

There are a few things that aren’t as easy to test in a development build, particularly splash screens. You can still get a lot of last-mile testing done with local builds by building a standalone release build:

`npx expo run:android --variant release`

or

`npx expo run:ios --configuration Release`

### Sharing builds

You can share Android APK builds and iOS simulator builds that were built on your local machine with other developers in your organization via EAS. Run `eas upload` to upload a build manually and generate a sharable link, or setup EAS as a [build cache provider](https://docs.expo.dev/guides/cache-builds-remotely/) to do this automatically. Other developers can then run `eas build:run` to download and run the build.

### Device builds

`npx expo run:android|ios` can also run your build on a device connected via USB.

For Android, after connecting your Android phone and ensuring that USB debugging is enabled, run `adb devices -l` to get the name of the device, and then plug that device name into `npx expo run:android --device [device-name]`.

For iOS, connect your device, ensure developer mode is enabled, and then run `xcrun xctrace list devices` to get the device UDID. Then run `npx expo run:ios --device [udid]`. Note that you may have to [open your ios folder in Xcode and select your development team](https://github.com/expo/fyi/blob/main/setup-xcode-signing.md) to fully complete this setup (the Expo CLI will let you know if this is needed).

If you are making a development build, you’ll be able to keep using that same build even after you disconnect from USB as long as the native runtime doesn’t change. Then you can later run `npx expo start` and scan the QR code.

## Generating signed production builds

EAS credentials management is pretty convenient, and you can get a lot of development and testing done with the simple signing setup that’s needed for running on emulators, simulators, or connected devices, so consider this a “break glass in case of emergency” measure. But, if you need to build locally with your EAS-generated production credentials, there is a way!

First, download the credentials you need via the `eas credentials` command. It will guide you to what you need for each platform (the upload keystore for Android and the distribution cert for iOS). Then run `npx expo prebuild --clean` to generate your native projects. If you [use multiple app variants](https://docs.expo.dev/tutorial/eas/multiple-app-variants/), make sure your environment is set to your production variant (if you set this with EAS environment variables, you can run `eas env:pull` to set these variables locally).

For Android, open up your **android** folder in Android Studio and go to **Build** → **Generate Signed App Bundle or APK**. Provide the keystore that you just downloaded.

For iOS, unzip your credentials you just downloaded and install them in the Keychain. Open up your **ios** folder in Xcode and check Signing and Capabilities under your Target to make sure signing is setup OK. It might be easier to regenerate the provisioning profile (there’s no harm in doing this). Then run **Product** → **Archive** to build.

## Conclusion

[Local builds](https://docs.expo.dev/guides/local-app-overview/) are a great addition to your repertoire for a lot of reasons, from local native code debugging to network access restrictions and more. They are complementary to cloud EAS Builds and Workflows, helping you get unstuck in a pinch while the rest of your automation continues to run on EAS. And, speaking of automation, it's always a great time to introduce fingerprints and EAS Update to speed up iteration even more by limiting how often and when you even need to rebuild at all.