RORK LABJP
TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the roundTOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round
Articles/Dev Tools
Dev Tools/2026-05-29Advanced

Rork × EAS Update Runtime Version Strategy — Upgrading Expo SDK Across 6 Apps Without Breaking Existing Users

A complete record of how I migrated 6 Rork-generated apps from Expo SDK 50 to 51 in three weeks without a single user-visible incident — runtimeVersion policies, full eas.json, a safety-gated publish script, and a 30-minute incident recovery playbook.

Rork515EAS Update6Runtime VersionExpo SDK2OTA6Production OperationsIndie Development20

Premium Article

I'm Masaki Hirokawa. I operate six mobile apps in parallel under Dolice Labs, and the single most misunderstood — and most accident-prone — Expo setting I've worked with is runtimeVersion.

This became viscerally clear in April 2026, one day after I bumped one of our Rork-generated wallpaper apps from Expo SDK 50 to 51. The build worked in my simulator. It worked in TestFlight. Yet within hours of releasing, three users still on the App Store-shipped SDK 50 build reported, "the icon layout changed overnight and my favorites are gone." The cause was simple: the JS bundle I built for SDK 51 was published via eas update --branch production to the same runtimeVersion the SDK 50 binaries were listening on.

The official docs say "make sure runtimeVersion matches," but they stop short of explaining what not matching looks like and how to keep yourself from making that mistake again. As one indie developer who has shipped over 50 million downloads since 2014, here is the full setup I now use to keep upgrading SDKs across six apps without breaking anyone.

Why Runtime Version Is the Quiet Landmine

EAS Update delivers JS bundles and assets to users without going through App Store / Google Play review. But the delivery target isn't really "a branch" — it's "any installed binary that shares the same runtimeVersion." Three facts converge here:

  1. If you use runtimeVersion: "appVersion", the runtimeVersion changes whenever you bump app.json version. Users on older versions stop receiving OTAs. Conversely, if you upgrade the SDK without bumping version, you ship a JS bundle built for the new SDK to native binaries built for the old one.
  2. SDK upgrades swap out the Hermes bytecode runtime and internal bridges. A JS bundle compiled against SDK 51's Hermes is unreadable to SDK 50's native. The Simulator and TestFlight won't catch this — they're always on the new binary.
  3. EAS Update doesn't tell users when delivery fails. The CLI prints Published in green. The device quietly keeps running the old JS. Sentry stays silent.

Without nailing all three of these down, you end up in the "it works on my device but the bug reports won't stop" hell.

Three Policies and When Each Is the Right Choice

runtimeVersion has roughly three modes. At Dolice Labs I pick per app based on release cadence and SDK migration frequency.

"appVersion" — for apps that release infrequently

This couples runtimeVersion to version in app.json, so it's hard to misconfigure. The downside: you can't mix multiple SDKs within a single version, so flexibility drops if you release often. Two of my six apps — the ones I push to the stores roughly monthly — use this.

Explicit SDK version — for apps where one SDK lives for a long time

Something like "runtimeVersion": "50.0.0". The runtimeVersion stays the same until you intentionally raise the SDK, so even publishing OTAs daily can never drift away from native. Two of my apps that I tune for AdMob revenue via roughly 30 OTAs a month use this.

Explicit semantic version — for splitting one codebase into two streams

"runtimeVersion": "2026.5.1" or similar, decoupled from the store-facing version. I used this when I shipped an iPad-specific UI on a different runtime in parallel with the iPhone build. Two parallel UIs can coexist and native changes can be confined to one stream.

Expo officially recommends "appVersion" for new apps, but for a Rork-generated codebase where the JS side churns frequently, locking to sdkVersion produces a lower incident rate in my experience.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Understand exactly how `runtimeVersion: "appVersion"` silently stops OTA delivery to existing-version users during SDK upgrades, with concrete failure cases I hit in production
Take home the full implementation set used to migrate 6 Rork apps from Expo SDK 50 to 51 in parallel — eas.json, branch/channel naming, and a publish script with built-in safety gates
Get a Sentry crash-free × EAS Update Webhook auto-halt mechanism that stops releases at the first sign of regression, plus a 30-minute recovery playbook for the day you accidentally ship native changes via OTA
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Dev Tools2026-06-28
Ship EAS Updates to a Few First, and Halt Automatically on Crash Rate
Because OTA updates reach everyone instantly, a bad update reaches everyone instantly too. Here is a three-layer design: ship EAS Update to a small canary, decide expand-or-halt from crash-free rate automatically, and hold a safety net on the device — with working code.
Dev Tools2026-06-24
When EAS Update Ships but the Bug Won't Die — Why OTA Stalls Silently, and How I Operate Around It
EAS Update can succeed and still fail to reach a slice of your users. These are field notes on runtimeVersion drift, updates that publish but never get adopted, and choosing the right rollback — with the instrumentation that actually helped on my Rork apps.
Dev Tools2026-05-01
EAS Update Published but Nothing Changes? Five Patterns That Quietly Break OTA Delivery in Rork
You ran eas update, the CLI showed a green Published, but your iPhone keeps loading the old code. Here are the five patterns I keep running into, plus a five-minute diagnostic flow you can use the next time OTA goes silent.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →