In a real app
Choosing the policy is a team decision. appVersion is simple but relies on the discipline of bumping version at every release that includes native changes; one forgotten bump and an update breaks production builds. fingerprint removes that risk by hashing whatever touches native code (native folders, config, native dependencies); since SDK 58, the default balanced preset ignores version bumps and hashes native modules by name and version, which cuts needless rebuilds. It still yields more runtime versions than a manual policy, so more builds to keep alive in parallel. A manual string suits projects that already follow a strict release process.
To check what a build embeds, eas build:list shows each build’s runtime version, and eas update:list each update’s; the two must match for the platform concerned. eas fingerprint:compare explains why two fingerprints differ, which avoids the “but I changed nothing native” conversation when a dependency updated a podspec. The Updates.runtimeVersion API gives the value at runtime, useful in an internal debug screen.
The most expensive pitfall: projects that keep runtimeVersion frozen at "1.0.0" for months “so updates reach everyone”. Sooner or later an update references a native module the old builds lack, and the crash hits precisely the users who never update their app.
Related terms
OTA update (EAS Update)
Shipping a new JavaScript bundle and its assets to installed apps without going through the stores; EAS Update is Expo’s service for it.
EAS Build
Expo’s hosted build service: profiles in eas.json, credentials management, and macOS and Linux runners for iOS and Android.
Prebuild (Continuous Native Generation)
The Expo command that generates the android and ios folders from app.json and config plugins instead of maintaining them by hand.
Development build
A debug build of your own app that includes expo-dev-client: your native modules, plus a launcher to connect to Metro.