Share an Expo/EAS build with testers — free

EAS internal distribution is Expo's built-in way to get a build onto a tester's phone without an app store. Set "distribution": "internal" on a build profile and EAS produces an installable artifact plus a shareable install page. It is a genuinely good system, and this page explains it properly before suggesting anything else.

Two things send teams looking for another route. On the free plan, every build waits in a low-priority queue behind every paying customer. And the install links live inside Expo's ecosystem, with access rules tied to your project settings. The build itself is portable, though: download the finished .apk or .ipa from the EAS build page, upload it to BetaDrop, and testers get one clean install page and QR code with no Expo account anywhere in the flow.

How EAS internal distribution actually works

Internal distribution is switched on per build profile in eas.json. The conventional profile name is preview:

eas.json
{
  "build": {
    "preview": {
      "distribution": "internal"
    }
  }
}

On Android, that one line changes the artifact. Profiles aimed at the Play Store produce an .aab, which a phone cannot install directly; with internal distribution, EAS changes the default Gradle command so the build produces an APK instead. Run the build and you get a file testers can actually install:

eas build -p android --profile preview

iOS takes more ceremony, because Apple requires it. Without an Apple enterprise membership, internal distribution means ad-hoc provisioning: the build embeds an allow-list of device UDIDs, and only devices on that list at build time can install it. You register tester devices with eas device:create, then build with a profile that includes them:

eas device:create
eas build -p ios --profile preview

Ad-hoc distribution needs a paid Apple Developer membership and covers at most 100 iPhones per membership year — Apple's ceiling is 100 devices per product family, per membership year (checked against developer.apple.com, August 2026). Adding a tester after the fact means registering their device and building again, or re-signing the existing build with an updated profile; in CI, EAS has a --refresh-ad-hoc-provisioning-profile flag for exactly this (checked against docs.expo.dev, August 2026).

When the build finishes, EAS gives it a shareable install URL built around a long, unguessable ID. By default anyone who has the URL can install the build, and a project setting can require an Expo login instead (checked August 2026). That is the whole system: profile, build, link.

Where it pinches

None of the above is badly designed. The friction is operational, and it lands hardest on the free plan.

  • The queue. Free-plan builds run in an explicitly low-priority queue behind every paid plan. As of August 2026, Expo's pricing page lists 15 Android and 15 iOS builds a month on the free plan, one running at a time with a 45-minute timeout, and warns that low-priority builds can wait 90+ minutes at peak. Those are Expo's numbers, not ours, and they can change; the point is that a fix-typo-and-rebuild loop with an hour of queue in the middle stops being iteration.
  • The ecosystem. The install link is an expo.dev page tied to your project. That is convenient when everyone lives in your Expo org, and a wall when they don't: flip the setting that requires sign-in and every tester needs an Expo account. Distribution config sits next to build config in someone else's dashboard either way.
  • iOS device churn multiplies the queue. Every new tester device means a rebuild or a re-sign, and on the free plan each rebuild is another trip through the same queue.

The BetaDrop path: same artifact, one clean link

The artifact EAS produces is a normal signed .apk or .ipa, and it is yours. BetaDrop's flow starts where the EAS build ends:

  1. Build as usual with your internal-distribution profile. Nothing about the build changes and the queue costs exactly what EAS already charges you — what changes is where the finished artifact goes next.
  2. Download the artifact from the build's detail page on expo.dev. Android internal builds hand you an .apk; iOS builds an .ipa.
  3. Upload it to BetaDrop: upload the APK or upload the IPA. Guest upload works with no account, up to 500 MB per file.
  4. Share the link or QR code. Testers open it in the phone's browser and install over the air, with no Expo account and no app to install first. Guest links last 24 hours; sign in free and you can push a link's expiry as far as 30 days.

Nothing in that flow depends on Expo. A bare React Native app built straight through Gradle and Xcode uses the identical steps, as does anything else that produces a signed binary. If only some of your apps are Expo apps, the distribution side can still be one flow.

To automate the hand-off, the BetaDrop CLI uploads from any terminal or CI job:

npm install -g @betadrop/cli
betadrop login --token bd_live_xxxxxxxx
betadrop publish ./build-1a2b3c.apk --notes "Sprint 14"

betadrop publish prints the install page URL; add --ci and it prints only the URL, ready to drop into a pull-request comment or a Slack message.

The iOS reality, both ways

Switching where the build is hosted does not change Apple's rules, and it would be dishonest to imply otherwise. An ad-hoc build installs only on devices whose UDIDs were in its provisioning profile at signing time. That constraint follows the build wherever it goes: Expo's install page, BetaDrop, or a file passed over AirDrop.

BetaDrop does not bypass Apple signing

BetaDrop generates the itms-services manifest automatically, so a tester installs straight from Safari. But the build must already be signed for that tester's device. If the provisioning profile does not cover the device, the install fails on every platform, ours included.

The workable routine: collect each tester's UDID with the UDID checker, register it with eas device:create or in the Apple Developer portal, rebuild, and share the new build. To see which devices a given .ipa actually covers, drop it into the IPA inspector or decode its profile with the provisioning profile decoder.

Android has no equivalent ceremony. A signed APK installs on any device whose owner allows browser installs, which is why the Android half of this page is three steps shorter.

When EAS internal distribution is the better call

  • You already pay for EAS. Paid plans build in the high-priority queue, so the main pain disappears, and the install link appears with zero extra steps exactly where the build finished. An extra upload buys you little.
  • You want access gated by Expo accounts. The sign-in requirement is a real feature when builds are sensitive and every tester is already in your Expo organization.
  • Your release process is EAS end to end. If EAS handles your credentials, updates and build automation, keeping distribution in the same dashboard keeps one audit trail.
  • Your iOS beta is heading to the App Store with external testers. TestFlight is the channel Apple built for external App Store testing, review step included. The TestFlight comparison covers when each makes sense.

BetaDrop earns its place when the queue is costing you afternoons, when testers should not need accounts of any kind, or when Expo apps are only part of what you ship and you want one distribution flow for everything.

Ship the build you already have

Your EAS build page is holding a finished .apk or .ipa right now. Upload it and hand testers a link that just installs.

Frequently asked questions

Do testers need an Expo account to install an EAS internal distribution build?

By default, no: anyone with the build's install URL can use it, and Expo offers a project setting that requires signing in to an Expo account instead (checked August 2026). BetaDrop removes the question entirely. The install page opens in the phone's browser and testers never create an account of any kind.

Why did EAS give me an .aab instead of an .apk?

Build profiles aimed at the Play Store produce an Android App Bundle, which a device cannot install directly. A profile with "distribution": "internal" switches the default Gradle command so the build produces an APK instead. BetaDrop distributes .apk files and does not accept .aab, so for direct tester installs, build with your internal-distribution profile.

Do I still need to register iOS device UDIDs if I use BetaDrop?

Yes. Ad-hoc signing is Apple's rule, not the distribution site's: an ad-hoc build installs only on devices whose UDIDs were in the provisioning profile when it was signed. Register devices with eas device:create or in the Apple Developer portal, then rebuild. BetaDrop generates the itms-services manifest for over-the-air install, but it cannot put an app on a device its profile does not cover.

Does this work for bare React Native apps that don't use Expo?

Yes. BetaDrop distributes any signed .apk or .ipa regardless of what produced it. A bare React Native app built straight through Gradle and Xcode, with no Expo modules and no EAS, follows the same flow: build, upload, share the link.

Is EAS internal distribution free?

There is a free plan. As of August 2026 it includes 15 Android and 15 iOS builds a month through a low-priority queue, and Expo's own pricing page warns of 90+ minute waits at peak times. Distributing a finished build adds nothing on BetaDrop's side: guest uploads need no account and accept files up to 500 MB.

iMobile Designs
Developed by iMobile Designs
Made with
in India