A teammate dropped the Shopify engineering post in our Android channel on a Thursday morning with just three words: "so... are we?" I run Android for a logistics app that's been on React Native since 2021, and for about two years I've been the person who gets pinged every time a native module update breaks our Android build while iOS ships clean. So when Shopify said they were walking away from React Native entirely and rebuilding everything in Swift and Kotlin using coding agents, it wasn't an abstract industry story to me. It was a Slack thread I had to actually respond to with something more useful than a shrug emoji.

I went and read the actual post, not just the headline going around. It's written by Mustafa Ali, and it lays out something more specific than "AI replaced our framework." The claim is narrower and, honestly, more interesting: coding agents changed the economics of building the same feature twice, not the technical merits of React Native versus native. Shopify says outright that their React Native apps are fast and that the framework remains solid. What changed is that the cost side of the "build once vs. build twice" equation moved.

I spent a weekend running a smaller version of their experiment against our own Android codebase, mostly to see if the same logic would hold up for a team that isn't Shopify-sized. This post is what I found in their writeup, what I tried myself, and where I think the analogy breaks down once you're not running a mobile org with hundreds of engineers and a dedicated AI tooling team.

Shopify's decision isn't a verdict that native beat React Native on technical grounds. It's a claim that agents made writing a feature twice cheaper than keeping one shared codebase in sync — and that only holds if you already have the review infrastructure in place to catch what the agent gets wrong.

What Shopify actually announced

Shopify went all-in on React Native back in 2020 for three reasons stated plainly in the post: stop building the same feature twice, let developers work across both platforms without being native specialists, and stop losing time chasing feature parity between iOS and Android. By their own account, React Native delivered on all three. As recently as January 2025, Mustafa Ali wrote that the future of React Native at Shopify was bright. This wasn't a framework that quietly failed them.

What changed is the assumption underneath the 2020 decision. Coding agents got good enough that Shopify could prototype rebuilding core parts of their biggest apps in Swift and Kotlin, using the existing React Native implementation as the reference spec, and have agents implement a feature on Android using the iOS version as reference material and vice versa. The post is careful to separate two things that get conflated a lot in the current AI discourse: agents didn't make native development itself faster in some general sense, they made the specific cost of maintaining parity across two native codebases — the thing React Native existed to solve in the first place — much lower.

The Shop app was first through the pipeline, going from proof of concept to a fully rebuilt native app live in both app stores in twelve weeks, a migration Shopify covered in a separate companion post. The main Shopify app, which has over 300 screens plus widgets, an Apple Watch companion, and Siri Shortcuts, is underway now. Everything else follows after that. It's a genuinely large-scale, multi-year bet being reversed inside of about a year of agent capability improvement.

The Helix checkpoint loop, and why the obvious approach doesn't work

The part of the post I found most useful wasn't the decision itself, it was the failure mode they describe hitting first. The tempting move is to point an LLM at the React Native codebase and ask it to one-shot the same feature natively. Shopify tried variations of this, including front-loading specs and task files before implementation, and their verdict was blunt: "you end up with a huge amount of unmaintainable code that can't be shipped."

That's the part I'd flag to anyone reading the announcement and hearing only "agents can rebuild your app now." They can't, not in one shot, not reliably. What Shopify built instead is a system called Helix that assumes the first attempt is wrong and structures the workflow around proving it isn't, one small slice at a time. A developer points Helix at a single screen. Helix reads the React Native implementation and proposes a sequence of checkpoints — small, ordered units of work reviewable in minutes. Each checkpoint has to prove its behavior with tests, get checked against the running app in a visual review, survive two separate adversarial code reviews, and get a human sign-off before it's committed and the next checkpoint starts. Review feedback carries forward, so later checkpoints in the same migration need less hand-holding than the first ones.

I don't have Shopify's actual Helix implementation, obviously, but the shape of a checkpoint definition for something like this is roughly what you'd expect if you translated their description into a config file:

checkpoint: order_summary_promo_row
source_reference: src/screens/OrderSummary/PromoRow.tsx
gates:
  - type: unit_tests
    must_pass: true
    coverage_target: existing_react_native_suite
  - type: visual_diff
    baseline: react_native_screenshot
    threshold: 0.98
  - type: adversarial_review
    reviewers: 2
    focus: [state_handling, edge_cases, accessibility]
  - type: human_approval
    required: true
on_pass:
  commit: true
  unblock_next_checkpoint: true
on_fail:
  retry_with_feedback: true
  carry_forward_notes: true

Whether or not that's close to what Shopify's config actually looks like, the underlying discipline is the interesting bit: no checkpoint unblocks the next one until it clears every gate. That's a very different posture from "let the agent write the PR and have a human skim it," which is what most teams, mine included, are actually doing with AI-assisted code today.

Getting the emulator out of the agent's feedback loop

The second problem Shopify calls out is one I've hit directly: agents can write code in seconds, but verifying that code on a simulator or emulator takes minutes, because the verification loop depends on the accessibility tree or on screenshots to figure out what state the app is in. On a fast-moving migration, that gap dominates everything. It doesn't matter how good the underlying model is if testing its output is the bottleneck.

Their fix is architectural: decouple business logic from the UI completely, so it can run headlessly on a desktop, and expose that logic to agents through a CLI instead of the UI layer. Here's roughly the pattern our own agent test was stuck in before I changed anything, verifying a promo code discount purely through the UI layer:

@Test
fun agentVerifiesDiscountApplied() {
    onView(withId(R.id.promoCodeField)).perform(typeText("SAVE10"))
    onView(withId(R.id.applyButton)).perform(click())
    onView(withId(R.id.orderTotalText)).check(matches(withText("$45.00")))
}

That test needs an emulator boot, a full activity launch, and Espresso's view-matching machinery to settle before it can assert anything. An agent iterating against this loses minutes per attempt, which adds up fast across a whole migration. The fix I tried, following Shopify's description, was pulling the pricing logic out from behind the UI entirely and exposing it through a plain JVM entry point:

class CartEngine(private val pricingRules: PricingRuleSet) {
    private var state = CartState.empty()

    fun applyPromoCode(code: String): CartState {
        state = pricingRules.apply(code, state)
        return state
    }

    fun currentState(): CartState = state
}

fun main(args: Array) {
    val engine = CartEngine(PricingRuleSet.default())
    when (args.getOrNull(0)) {
        "apply-promo" -> println(engine.applyPromoCode(args[1]).toJson())
        "inspect" -> println(engine.currentState().toJson())
        else -> println("unknown command")
    }
}

Running ./gradlew :cart:cli:run --args="apply-promo SAVE10" gets a JSON result back in well under a second, no emulator involved. That's not a novel idea on its own — pulling logic out from behind the UI for testability is old advice — but wiring it up specifically so an agent can drive it as a command-line tool, and only fall back to the emulator when a real UI question needs answering, made my own agent loop noticeably less painful to babysit. Shopify describes going further and giving agents a remote mode that drives the simulator UI directly through commands rather than by inspecting the layout tree, for the cases where UI verification genuinely can't be skipped.

What the post is careful not to claim

It's worth sitting with the line "React Native apps can be fast. Ours are." for a second, because it undercuts the version of this story that's spreading on social media, which is "Shopify proved native beats React Native." That's not the argument being made. The argument is about the relative cost of maintaining two native codebases versus one shared one, and that cost dropped because agents can now translate, test, and review across platforms in a way they couldn't in 2020, or even in early 2025.

The other distinction worth catching is brownfield versus greenfield migration. When Shopify moved to React Native years ago, they picked a brownfield approach for their biggest apps — gradually replacing pieces in place, because a full rewrite would have meant pausing feature work for years. This time they went greenfield, rebuilding from scratch, specifically because agents referencing the existing React Native version as a spec made a full rewrite fast enough to be worth the clean slate.

Brownfield vs. greenfield migration: brownfield means incrementally replacing parts of an existing codebase while it keeps shipping; greenfield means starting a new codebase from scratch and cutting over once it's ready. The choice usually comes down to whether a full rewrite is fast enough to be worth losing incremental delivery along the way.

That distinction matters if you're the one deciding whether to follow suit, because a greenfield native rebuild assisted by agents is a very different commitment than gradually swapping RN screens for native ones. Shopify picked greenfield because their prototypes showed it was substantially faster than pre-agent estimates, not because greenfield is generally the safer default.

The pushback worth taking seriously

Not everyone read the announcement the same way I did. Jamon Holmgren, who runs the React Native consultancy Infinite Red, pointed out on X that the Shop app hadn't yet adopted React Native's New Architecture — the Fabric renderer and TurboModules rework that was built specifically to cut down bridge overhead and improve startup time.

"The one thing that was almost certain to improve startup time hadn't happened yet," — Jamon Holmgren, on Shopify's Shop app migration

That's a fair challenge for anyone on Android specifically, because the old bridge architecture's serialization overhead between JavaScript and native code tends to show up more painfully on Android than iOS, where garbage collection pauses and JNI call overhead compound the problem. If Shopify's reported performance wins came partly from finally getting off an older architecture rather than purely from going native, that changes how much of the story is "agents changed the math" versus "we were overdue for a framework upgrade anyway." Shopify hasn't published a breakdown that isolates those two variables, at least not in the post I read, so I'd hold the performance numbers loosely until someone does that comparison directly.

Where I think this stops generalizing

Shopify has conditions most teams don't: a large, motivated mobile org, real investment in agent tooling and review infrastructure, and engineers who can supervise native output in both Swift and Kotlin. Helix's checkpoint gating, the CLI-driven headless testing, the two-reviewer adversarial gate — none of that is free, and building it is its own multi-quarter engineering project sitting underneath the migration everyone's talking about.

For a smaller Android team like mine, the calculation isn't just "can an agent write Kotlin now." It can, reasonably well. The real question is whether you have — or are willing to build — the gating discipline that keeps agent output from turning into exactly the unmaintainable slop Shopify explicitly warns about. Without that, going native with agent help just moves the maintenance burden from "syncing two RN screens" to "reviewing agent-generated Kotlin and Swift that both need to stay behaviorally identical," which is not obviously less work if nobody's built the checkpoint infrastructure to catch drift early.

Going fully native means giving up over-the-air JS bundle updates. A React Native app can ship a hotfix without an app store review cycle; a native Android build can't skip the Play Store review, even with staged rollouts and faster turnaround than Apple's. If your team leans on OTA patches for anything time-sensitive — compliance fixes, payment bugs, anything you can't afford to wait a day or two on — that's a real capability you're trading away, not a footnote.

None of that means the decision is wrong for Shopify. It means the announcement describes a specific set of preconditions, and skipping straight to "we should go native too" without checking whether you actually have those preconditions is how you end up with a slower, more expensive migration than the one you were trying to avoid.

What I'd actually check before following their lead

After reading the post twice and running my own small-scale version of it, here's the checklist I'd actually work through before recommending a native rewrite to my own team, roughly in the order I'd tackle them:

  • Do we have engineers who can review Kotlin and Swift output critically, or would we be trusting agent output in a language nobody on the team reads fluently?
  • Can we build something like a checkpoint-gated review loop, even a lightweight version, before we start generating native code at scale?
  • How cleanly can our business logic be pulled out from behind Activities, Fragments, and the RN bridge, and how much of it is already tangled into UI code that would need untangling first?
  • How dependent are we on OTA JS updates today, and what's our actual tolerance for a full app store review cycle on urgent fixes?
  • Is our current React Native performance complaint actually a framework ceiling, or are we just behind on adopting the New Architecture and blaming the wrong thing?

Every one of those questions has a real, checkable answer for your specific team. None of them are answered by "Shopify did it and it worked for them."

I'm not migrating our app off React Native this quarter, and probably not next quarter either. We don't have anything close to Helix's review gating built, and we still lean on OTA patches more than I'd like to admit for a payments-adjacent app. What I am doing is picking our highest-churn screen, the one that causes the most parity bugs between platforms, and rebuilding just that one natively with an agent, checkpoint by checkpoint, by hand-rolling a much smaller version of the gating loop Shopify describes. If that goes well, it tells me something real about whether the economics actually work for a team our size, instead of just borrowing Shopify's conclusion because their post was well written.

Sources: Mustafa Ali — Native is now the future of mobile at Shopify, Shopify Engineering — Migrating Shop app from React Native to native