Custom Dev Client + OTA: Why You Need Both for Seamless Updates
Learn how combining expo-dev-client with EAS Update lets you ship OTA updates without being limited to Expo Go, and how to configure them correctly.
Insight
When you move beyond the Expo Go sandbox, a custom development client becomes essential. It lets you include native modules that Expo Go doesn't support, while EAS Update still handles over‑the‑air JavaScript bundles. The trick is to keep the runtime version in sync between the dev client and the OTA manifest; otherwise users will see a "New update available" banner that never applies. By pinning the runtime version to your eas.json build profile and exposing it via expo.runtimeVersion, you guarantee that OTA updates only land on compatible native binaries.
Example
// eas.json
{
"cli": {"version": ">=3.0.0"},
"build": {
"production": {
"developmentClient": true,
"runtimeVersion": "1.2.0"
}
}
}
// app.json (or app.config.ts)
export default {
expo: {
runtimeVersion: { policy: "appVersion" },
plugins: ["expo-dev-client"]
}
};
Takeaway
Create a custom dev client for native features, lock its runtimeVersion in eas.json, and let EAS Update handle JavaScript patches. This combo gives you the flexibility of bare React Native with the convenience of OTA updates.