Glean 拾遗
Daily /2026-11-13 / Shopify's 12-week rewrite: agents wrote code, humans rebuilt the loop

Shopify's 12-week rewrite: agents wrote code, humans rebuilt the loop

Source shopify.engineering Glean’d 2026-11-13 06:00 Read 19 min
AI summary

Thirty Shopify engineers moved a 300+ screen app from React Native to Swift and Kotlin in 12 weeks, with agents writing most of the implementation. The post is about what surrounds the code: business logic runnable without a device, the Reflex architecture and a CLI that loads any screen in milliseconds, one shared architecture across iOS and Android, an example and .md file per screen, and CI that fails when the two platforms diverge. Spec-driven development was abandoned because specs went stale in days; the legacy React Native app became the reference. The second half covers the bottleneck shift — laptops saturating on emulators, review and merge queues, tickets lagging behind Slack-reported fixes — and the responses: a remote dev environment for agents, adversarial agent-first review, and a self-healing loop that reproduces crashes every 15 minutes. Results: Android launch 1.71s to 0.87s, binary 80.4MB to 47.6MB.

Original · 19 min
shopify.engineering ↗
§ 1

Thirty engineers just rebuilt the Shopify app from React Native to Swift and Kotlin in 12 weeks. The app has more than 300 screens, home and lockscreen widgets, an Apple Watch app, complications, and Siri Shortcuts.

Agents wrote most of the code. If you have read our other posts in this series, that won’t be a surprise. The real surprising part is how much we had to change around the code.

Once agents started producing large amounts of code quickly, everything surrounding that code became more important: the architecture, tests, code review process, machines running emulators, and coordination between people.

We changed the way the app is built so agents could work inside a workflow with fast feedback, clear patterns, and checks that kept them on the rails.

三十名工程师用 12 周把 Shopify App 从 React Native 重写成 Swift 和 Kotlin。这个 App 有 300 多个页面,还有主屏和锁屏小组件、Apple Watch App、表盘复杂功能,以及 Siri Shortcuts。

大部分代码是 Agent 写的。如果你读过本系列的其他文章,这并不意外。真正意外的是,代码之外有太多东西要改。

Agent 一旦开始快速产出大量代码,代码周围的一切就变得更重要:架构、测试、代码评审流程、跑模拟器的机器,以及人与人之间的协作。

我们改了 App 的构建方式,让 Agent 能在一个工作流里干活:反馈快、模式清晰,还有检查把它们拉回正轨。

§ 2

The posts we’ve shared over the last few weeks covered the main pieces of that system:

  • Native is now the future of mobile at Shopify
  • Helix, the internal tool powering our migration
  • Our remote development environment for agents
  • Reflex: an architecture for building mobile apps with agents

This is about how those pieces fit together, and what we learned about setting up a workflow where agents can move fast while humans still validate, review, and approve what ships.

过去几周发布的一系列文章,讲了这个系统的主要部件:

  • 原生已是 Shopify 移动端的未来
  • Helix,支撑这次迁移的内部工具
  • 我们给 Agent 用的远程开发环境
  • Reflex:用 Agent 构建移动 App 的架构

本文讲这些部件如何拼在一起,以及我们在搭建工作流时学到了什么:Agent 可以跑得快,但人类仍然要验证、评审并批准最终发布的内容。

§ 3

Before we migrated screens, a small group of engineers prepared the system around the agents: the architecture, tooling, and the feedback loop.

At first glance, that can look backwards. If an agent can generate thousands of lines of code in an afternoon, why spend weeks beforehand writing the screens?

Because speed on its own gets you a lot of code, not a good app. The system around the agent has to tell it when the output is wrong, and the architecture has to steer it toward code that is clean, consistent, and performant. Left alone, agents won’t do that.

迁屏幕之前,一小队工程师先给 Agent 搭好外围系统:架构、工具和反馈回路。

乍看之下,这有点像倒着来。如果 Agent 一个下午就能生成几千行代码,为什么还要提前花几周写屏幕?

因为速度本身只能给你一堆代码,给不了好 App。Agent 周围的系统必须告诉它输出哪里不对,架构必须把它引向干净、一致、性能达标的代码。没人管,Agent 不会自己做到。

§ 4

The work was not just architecture in the usual sense. We were completely rethinking how mobile apps should be built in the age of AI agents:

  • Business logic that runs without a device for fast feedback loops
  • The Reflex architecture and a CLI that can load any screen in milliseconds
  • One architecture shared by iOS and Android
  • Clear examples and .md files for every new screen to follow
  • Repository guardrails that fail when the code drifts

For humans, architecture can live partly in people's heads. For agents, it cannot. It has to be visible in file structure, architecture.md files, skills, naming, state shapes, method signatures, CLI output, lint rules, test fixtures, and CI failures.

That changed how we built the app. We were still designing for engineers, but we were also designing for agents that need repeatable patterns, fast feedback, and very clear error messages.

这项工作的重点不只是传统意义上的架构。我们在彻底重想:AI Agent 时代,移动 App 该怎么造:

  • 业务逻辑不依赖设备就能跑,反馈才快
  • Reflex 架构,以及能在毫秒内加载任意屏幕的 CLI
  • iOS 和 Android 共用一套架构
  • 每个新屏幕都有清晰示例和 .md 文件可循
  • 仓库里有护栏,代码一跑偏就失败

对人来说,架构可以部分装在脑子里。对 Agent 不行。架构必须看得见:文件结构、architecture.md、skills、命名、状态形状、方法签名、CLI 输出、lint 规则、测试 fixture,以及 CI 失败信息。

这也改变了我们构建 App 的方式。我们仍然为工程师设计,但同时也为 Agent 设计——它们需要可重复的模式、快速反馈,以及非常明确的报错。

§ 5

Before this work, an agent had the same feedback loop as a human: build the app, start the emulator or simulator, navigate to the screen, look at the result by taking screenshots, analyze it, make a change, and try again. That loop takes several minutes per iteration, and agents are bad at every step that depends on visual navigation and context that lives outside the code.

After the architecture work, an agent could run most of the screen without starting a device. It could load a ViewModel from the terminal, trigger actions, inspect state, and run deterministic checks in milliseconds. That fast feedback loop is what made the migration possible at the speed we reached later.

We didn’t get faster by asking agents to take bigger swings. We got faster by making the work smaller and the feedback loop tighter.

在这项工作之前,Agent 的反馈回路和人一样:构建 App,启动模拟器,导航到屏幕,截图看结果,分析,改代码,再试。每轮要花好几分钟,而且凡是依赖视觉导航、依赖代码之外上下文的步骤,Agent 都不擅长。

架构工作完成后,Agent 不启动设备就能跑大部分屏幕逻辑。它可以从终端加载 ViewModel,触发 action,查看 state,在毫秒内跑确定性检查。正是这个快速反馈回路,让后来的迁移达到了那样的速度。

我们变快,不是因为让 Agent 下更大的注。我们变快,是因为把工作切小,把反馈回路收紧。

§ 6

About 30 engineers worked on the rewrite, organized in pods of two, with each pair owning an area of the app across both platforms. The two engineers in a pod paired most of the day, each one steering multiple agents at the same time. Agents kept working overnight and on weekends, so every morning started with a queue of PRs to review. We kept the pods small on purpose. Agents gave each pair the implementation capacity to cover a whole product area. What each pod needed was clear ownership, fast decisions, and shared context.

We didn’t organize the migration as one iOS team and one Android team. Each pair owned a product area end to end. Agents did much of the implementation, but humans still owned the architecture, product behavior, and final judgment about what was good to ship.

大约 30 名工程师参与重写,按两人一组分成多个 pod,每组负责一个 App 领域,同时覆盖两个平台。组里两人大部分时间结对,各自同时驾驭多个 Agent。Agent 会通宵、周末继续干活,所以每天早上都有一队 PR 等着评审。我们刻意把 pod 保持得很小。Agent 给了每组足够的实现能力,覆盖整个产品域。每个 pod 真正需要的是清晰归属、快速决策和共享上下文。

我们没有把迁移拆成一个 iOS 团队加一个 Android 团队。每组端到端负责一个产品域。Agent 承担了大量实现,但架构、产品行为,以及“什么能发布”的最终判断,仍然由人负责。

§ 7

Our first principle was consistency. Consistency of architecture, so agents could create PRs that followed the same shape. Consistency between Android and iOS, so the same screen exposed the same state, actions, and behavior on both platforms. An iOS ViewModel for the orders screen looks like the Android ViewModel, whether you’re reading the Swift or Kotlin version.

We deliberately prioritized consistency over platform-specific architecture. Some of the code is less idiomatic than what an iOS or Android purist might write. We are comfortable with that tradeoff because of what we get in return:

  • Every migrated screen becomes an example for the next one
  • One PR contains the changes for both platforms
  • An engineer who knows one platform can review a PR on the other
  • Architecture guidelines are written once for both platforms
  • Tests can run the same merchant journey across iOS and Android

我们的第一原则是一致性。架构一致,Agent 才能开出形状相同的 PR。Android 和 iOS 之间一致,同一个屏幕在两个平台暴露相同的 state、action 和行为。订单屏幕的 iOS ViewModel 和 Android ViewModel 长得一样,无论你读的是 Swift 还是 Kotlin 版本。

我们刻意把一致性放在平台特有架构之前。有些代码不如 iOS 或 Android 原教旨主义者写得那么地道。我们接受这个取舍,因为换回来的是:

  • 每个迁完的屏幕,都是下一个屏幕的示例
  • 一个 PR 包含两个平台的改动
  • 懂一个平台的工程师,能评审另一个平台的 PR
  • 架构规范只写一次,两个平台共用
  • 测试可以在 iOS 和 Android 上跑同一条商家旅程
§ 8

This is also what makes the argument from our first post work in practice. Building native apps for two platforms doesn’t have to cost twice as much if the second platform follows the same architecture. That only works if both sides keep the same shape.

In an agentic workflow, consistency is not aesthetic. It’s infrastructure. It’s what lets humans compare intent across platforms, agents to reuse examples, and CI to detect drift before a reviewer has to find it by hand.

We enforce that consistency. CI fails when iOS and Android diverge in ways the architecture doesn’t allow.

这也让第一篇文章里的论点真正落地:为两个平台构建原生 App,未必需要双倍成本,前提是第二个平台沿用同一套架构。而这只在两边保持相同形状时才成立。

在 Agent 工作流里,一致性不是审美问题,而是基础设施。它让人能跨平台比较意图,让 Agent 复用示例,也让 CI 在评审者手工发现之前就检测到漂移。

我们会强制执行这种一致性。iOS 和 Android 出现架构不允许的分叉时,CI 直接失败。

§ 9

TL;DR: No vibe coding.

In our first post, we wrote that asking an LLM to one-shot a rewrite produces a huge amount of code that can’t be shipped. Guardrails are our answer to that problem.

With a strong architecture and the right checks, agents have clear directions and less room to improvise in places where improvisation creates maintenance cost. Without those constraints, an agent can produce code that compiles, passes a narrow test, and still leaves humans with a codebase nobody wants to own.

The system has to answer three questions for every agent-written change:

  • Does it follow the architecture?
  • Does it behave like the existing app?
  • Can a human review the intent without reading a giant diff line by line?

Different parts of the system answer those questions.

The architecture guidelines, examples, lint rules, and divergence checks answer the first one. Helix and the legacy React Native app answer the second one. Small checkpoints, cross-platform PRs, and agent-first review answer the third.

The important thing is that the guardrails live in the workflow, not only in a document. A document explains why the rule exists; CI decides whether the rule was followed.

Agents need more than instructions. They need a way to discover when they are wrong.

TL;DR:不搞 vibe coding。

第一篇文章里我们写过:让 LLM 一次性完成重写,会产出一大堆没法发布的代码。护栏就是我们对此的答案。

有了强架构和合适的检查,Agent 方向清楚,在容易产生维护成本的地方也没那么多即兴发挥的空间。没有这些约束,Agent 能写出编译通过、窄测试也过,但最后留给人的是一个没人想接手的代码库。

对每个 Agent 写的改动,系统必须回答三个问题:

  • 它遵循架构吗?
  • 它的行为和现有 App 一致吗?
  • 人能不用逐行读巨大 diff,就评审它的意图吗?

系统的不同部分分别回答这些问题。

架构规范、示例、lint 规则和分叉检查回答第一个。Helix 和旧版 React Native App 回答第二个。小 checkpoint、跨平台 PR 和 Agent 先评审回答第三个。

关键点是:护栏要活在工作流里,不能只活在文档里。文档解释规则为什么存在;CI 决定规则有没有被执行。

Agent 需要的不只是指令。它需要一种方式,能发现自己什么时候错了。

§ 10

We tried spec-driven development first: write a spec for a screen, give it to the agent, review the result. It didn’t work.

The specs went out of date almost immediately. By the time the agent was working on the third checkpoint of a screen, the spec written for the first checkpoint was already incomplete or wrong. Nobody wanted to maintain a parallel description of behavior that already existed in the product.

For this migration, the existing app was a better spec than a document. The legacy React Native screen already described the states, actions, edge cases, empty states, loading behavior, and navigation. Helix reads that reference, splits the migration into small checkpoints, and verifies each checkpoint against the original app instead of against a long-lived written spec.

We asked agents to converge on an existing product instead of inventing a new one from scratch. For that kind of work, a live reference beats a written spec, hands down.

我们先试了 spec 驱动开发:给一个屏幕写 spec,交给 Agent,再评审结果。行不通。

Spec 几乎立刻就过期。Agent 做到一个屏幕的第三个 checkpoint 时,为第一个 checkpoint 写的 spec 已经不全或者错了。没人愿意维护一份和产品里已有行为并行的描述。

这次迁移里,现有 App 比文档更像好 spec。旧版 React Native 屏幕已经写明了 state、action、边界情况、空状态、加载行为和导航。Helix 读取这份参照,把迁移拆成小 checkpoint,并拿每个 checkpoint 和原 App 对照验证,而不是对照一份长期维护的书面 spec。

我们让 Agent 收敛到一个现有产品,而不是从零发明一个新产品。对这类工作,活参照完胜书面 spec。

§ 11

New features are different. When there is no existing screen to compare against, the rules may be foreign… That is our next challenge.

The lesson from the migration is narrower but very useful: agents don’t need a perfect first attempt. They need a reference, a small next step, and a fast way to check whether they moved closer to the target.

新功能不一样。没有现成屏幕可对照时,这些规则可能很陌生……这是我们的下一个挑战。

这次迁移的教训更窄,但非常有用:Agent 不需要第一次就做到完美。它需要一份参照、一个小步的下一步,以及一种快速检查自己有没有更接近目标的方式。

§ 12

Once writing code was no longer the slowest part of the system, the bottleneck moved.

This is the part of agentic development the industry is still absorbing. A lot of the conversation is still about how fast agents can generate code. But great teams don’t ship generated code. They ship reviewed, tested, integrated, secure, maintainable software.

When code generation speeds up, every downstream constraint becomes more visible.

This looks a lot like Jevons paradox. When something becomes more efficient, we often consume more of it. That’s what happened to us here. Agents made implementation faster, but that didn’t mean the team had less work to do. It meant we could take on more work with the same team size: more checkpoints, fixes, parallel migration streams, review, CI, decisions…

Written code is no longer a scarce resource. The scarcity has shifted to the decision-making around which code should exist, and then safely getting it into the product.

With put these productivity gains back into the roadmap.

写代码不再是系统里最慢的环节之后,瓶颈就转移了。

这是 Agent 开发中行业还在消化的部分。很多讨论仍然围绕 Agent 生成代码有多快。但优秀团队发布的不是生成出来的代码,而是经过评审、测试、集成,安全且可维护的软件。

代码生成一加速,下游每一个约束都会变得更显眼。

这很像杰文斯悖论:某件事效率变高,我们往往会消费更多。我们也遇到了这个情况。Agent 让实现变快,但这不意味着团队活少了。它意味着同样规模下我们能接更多工作:更多 checkpoint、修复、并行迁移流、评审、CI、决策……

写出来的代码不再是稀缺资源。稀缺的变成了决策:哪些代码应该存在,以及如何把它安全地送进产品。

我们把这份效率红利重新投回路线图。

§ 13

Agents still need machines. They need emulators for UI tests and visual checks. They need compilers. They need build caches and disk space. A laptop can’t run many emulators before compilers and emulators start competing for CPU, memory, and disk.

One engineer running three agents can saturate a laptop, so we built a remote development environment for agents. The agentic workflow only works if the compute model can keep up with it. Otherwise the agent is fast, but the machine becomes the queue.

Agent 仍然需要机器。UI 测试和视觉检查要模拟器,编译要编译器,还要构建缓存和磁盘空间。笔记本跑不了几个模拟器,编译器和模拟器就开始抢 CPU、内存和磁盘。

一个工程师同时跑三个 Agent 就能把笔记本压满,所以我们给 Agent 搭了远程开发环境。Agent 工作流要想成立,算力模型必须跟得上。否则 Agent 是快,但机器成了队列。

§ 14

Agents write faster than humans can approve. Code that takes minutes to write can still take days to merge. It doesn't matter how fast agents are if humans can’t responsibly understand, review, and land the changes.

We still require human code review on every PR, so the reviewer judges intent, architecture fit, product. behavior, and whether this change belongs on a codebase that millions of merchant depend on.

The question we get the most is how pods of two people can review 100 times more code. The honest answer is that they cannot, not line by line. So we changed the order of review:

Agents are the first reviewer. Every PR gets an adversarial review against our architecture guidelines before a human looks at it. Obvious issues should be fixed before the reviewer spends attention on the change.

We changed the size and shape of the work. A PR is a small checkpoint, not a full screen. The size of a diff a human can read is a constraint we give to the agent. One PR contains both platforms, so the reviewer can compare iOS and Android side by side instead of reviewing the same behavior twice, days apart.

The human is the last step. Instead of scrutinizing every line of code, their job is to judge intent, architecture fit, product behavior, and whether this change belongs in a codebase that millions of users depend on.

Agent 写得比人批得快。几分钟写出来的代码,可能要几天才能合并。如果人没法负责任地理解、评审并落地这些改动,Agent 再快也没用。

我们仍然要求每个 PR 都有人工代码评审,评审者要判断意图、架构契合度、产品行为,以及这个改动该不该进入一个数百万商家依赖的代码库。

我们最常被问:两个人的 pod 怎么能评审多出 100 倍的代码?老实说,逐行评审做不到。所以我们改了评审顺序:

Agent 是第一评审者。每个 PR 在人类看之前,都会先按架构规范做一轮对抗式评审。明显问题应该在人花注意力之前就修掉。

我们改了工作的尺寸和形状。一个 PR 是一个小 checkpoint,不是一整个屏幕。人能读多大的 diff,这是我们给 Agent 的约束。一个 PR 同时包含两个平台,评审者可以并排比较 iOS 和 Android,而不是隔几天把同一套行为评审两遍。

人是最后一步。人的工作不是逐行抠代码,而是判断意图、架构契合度、产品行为,以及这个改动该不该进入一个数百万用户依赖的代码库。

§ 15

At the end of each day during this migration build, an agent went through every review comment left that day and used them to update our skills and Architecture.md. A comment made once on one PR became a rule for every PR after it. Each day the system got a bit better, and the number of changes requested per PR kept going down.

这次迁移构建期间,每天结束时,都会有一个 Agent 过一遍当天留下的所有评审意见,用它们更新我们的 skills 和 Architecture.md。一个 PR 上提过一次的意见,会变成之后每个 PR 的规则。系统每天好一点,每个 PR 被要求的改动数量也一路下降。

§ 16

We work through the queue with agents now. Agents rebase branches, fix merge conflicts, investigate CI failures, fix flaky tests, and help get PRs through the last mile. That work used to be annoying but manageable when each engineer had a smaller number of branches in flight. With agents producing more checkpoints, the merge queue itself became part of the product development system.

If agents increase the number of PRs, you also need to use agents to improve the machinery around PRs to move items on the merge queue. Otherwise the team just moves waiting time from implementation to integration.

现在我们也用 Agent 来消化队列。Agent 会 rebase 分支、解决合并冲突、排查 CI 失败、修 flaky 测试,帮 PR 走完最后一公里。以前每个工程师同时有多个分支在跑,这些活虽然烦但还管得过来。Agent 产出更多 checkpoint 之后,合并队列本身也成了产品开发系统的一部分。

如果 Agent 让 PR 数量增加,你就也得用 Agent 去改进 PR 周边的机器,让合并队列里的条目动起来。否则团队只是把等待时间从实现挪到了集成。

§ 17

Tracking work also got harder. Tickets stopped being the source of truth for everything. A bug gets reported in a Slack thread, someone points an agent at it, and the fix is up for review before anyone has had time to create a ticket.

Crashes don’t always need a human to start the loop anymore. We added a new self-healing loop that runs every 15 minutes and looks for new crashes. When it finds one, our Slack agent River, reproduces it in the remote development environment and opens a PR with the fix. The first time a human hears about the crash may be when the PR shows up for review.

Stories, tasks, and bug tickets were designed for a world where writing the fix was the slow part. That is not true anymore. The real problem now is multiple engineers, each with their agents, fixing the same bug at the same time without knowing it.

That’s one reason we split the team into small pods of twos that own main areas of the app. If an issue is in orders, the orders pod picks it up. If it’s in products, the products pod takes it. It’s not a perfect answer, and we haven’t found a tool that fully replaces the ticket board, but ownership by area keeps us from duplicating work today.

As you can see, every time we removed a bottleneck, the next one showed up right behind it. The agent itself is rarely the only problem anymore. The problems moved to machines, CI, review, merging, and coordination.

跟踪工作也变难了。Ticket 不再是一切的事实源。一个 bug 在 Slack 线程里被报出来,有人让 Agent 去处理,修复很快就进了评审,甚至没人来得及建 ticket。

崩溃也不一定再需要人来启动循环。我们加了一个自愈循环,每 15 分钟跑一次,寻找新崩溃。发现崩溃后,我们的 Slack Agent River 会在远程开发环境里复现,并开一个带修复的 PR。人第一次听说这个崩溃,可能就是在 PR 等着评审的时候。

Story、任务和 bug ticket 是为“写修复很慢”的世界设计的。现在不是了。真正的问题是多个工程师,各自带着 Agent,同时修同一个 bug 却互不知情。

这也是我们把团队拆成两人小组、各自负责 App 主要领域的原因之一。问题出在订单,订单 pod 接;出在商品,商品 pod 接。这不是完美答案,我们也没找到能完全替代 ticket 板的工具,但按领域归属,至少今天能避免重复劳动。

你看,每移除一个瓶颈,下一个马上就跟上来。Agent 本身很少再是唯一的问题。问题转移到了机器、CI、评审、合并和协调上。

§ 18

A software engineer's job is to solve problems. There are still plenty of problems to solve. The problems are just different than before, and a single engineer is now solving 10 of them at the same time.

Before, a large share of the work was manually turning intent into code. In this migration, agents took on much more of that mechanical implementation work. But the responsibility didn’t disappear, it just moved. Engineers spent more time shaping architecture, writing the patterns agents would copy, designing feedback loops, reviewing intent, debugging systems around the code, and holding a high quality bar.

The Reflex architecture, Helix, remote development environment, review process, the ownership model were all part of the same answer: build a system where agents can do useful work without turning the codebase into a mess.

This is a different engineering job compared to a few months ago, but the scope remains massive and exciting.

软件工程师的工作是解决问题。要解决的问题仍然很多。只是问题变了,而且一个工程师现在同时解十个问题。

以前,很大一部分工作是把意图手工变成代码。这次迁移里,Agent 接管了更多机械实现。但责任没有消失,只是转移了。工程师花更多时间塑造架构、写 Agent 会照抄的模式、设计反馈回路、评审意图、调试代码周围的系统,并守住质量底线。

Reflex 架构、Helix、远程开发环境、评审流程、归属模型,都是同一个答案的一部分:搭一个系统,让 Agent 能干活,同时不把代码库搞成一团乱麻。

和几个月前相比,这是另一种工程工作,但范围依然巨大,依然让人兴奋。

§ 19

The migration was not only about how we build the app. It also changed what merchants get.

We moved Shopify Mobile from a React Native app running on the New Architecture to fully native Swift and Kotlin apps, without asking our users to do anything. Our users stayed logged in and preferences carried over. From their point of view, the app updated and kept working.

But under the hood, the app changed a lot:

Launch time dropped by about 50% on Android (P50 from 1.71s to 0.87s) and 14% on iOS (P50 from 0.70s to 0.60s).

The Android binary became 40% smaller (from 80.4MB to 47.6MB)

这次迁移不只改了 App 的构建方式,也改变了商家得到的东西。

我们把 Shopify Mobile 从跑在新架构上的 React Native App,换成了完全原生的 Swift 和 Kotlin App,没让用户做任何事。用户保持登录,偏好也带了过来。从他们的角度看,App 更新了,然后继续能用。

但底层变化很大:

Android 启动时间下降约 50%(P50 从 1.71s 降到 0.87s),iOS 下降 14%(P50 从 0.70s 降到 0.60s)。

Android 安装包缩小 40%(从 80.4MB 降到 47.6MB)。

§ 20

Android app download size drops from about 80 MB to about 48 MB.

Android App 下载体积从约 80 MB 降到约 48 MB。

§ 21

Android Memory usage is roughly half of what it was in React Native (P50 from 470MB to 200MB)

iOS peak memory dropped by more than 70% (P50 from 730MB to 190MB)

Android 内存占用大约是 React Native 时期的一半(P50 从 470MB 降到 200MB)。

iOS 峰值内存下降超过 70%(P50 从 730MB 降到 190MB)。

§ 22

Android memory usage falls over time, shown at P50 and P75.

Android 内存占用随时间下降,图中展示 P50 和 P75。

§ 23

iOS peak memory drops from about 730 MB to about 190 MB across app versions.

iOS 峰值内存随 App 版本从约 730 MB 降到约 190 MB。

§ 24

The app now feels fully native. We can use platform transitions, smoother animations, and native page behavior without fighting the abstraction layer.

When new platform capabilities arrive, we can support them directly. For example, we were able to support iPhone Duo on day one.

Stability improved too. On Android, crash-free sessions moved from 99.66% on React Native to 99.98% on native. iOS stayed above our 99.95% target. We also added a self-healing process so agents can detect and fix crashes automatically.

And the app is now agent-ready: every screen has state and actions exposed through an introspectable ViewModel. Using the Reflex architecture and the CLI, Agents can test much of the app without launching a simulator, and anyone at Shopify can use River to build and validate a mobile change.

That is the result we wanted: a faster app for merchants, and a codebase that is easier for humans and agents to keep improving and working with.

App 现在完全是原生的感觉。我们可以用平台转场、更顺的动画和原生页面行为,不用再跟抽象层较劲。

新平台能力出现时,我们能直接支持。比如 iPhone Duo,我们第一天就支持了。

稳定性也提升了。Android 上,无崩溃会话从 React Native 的 99.66% 提升到原生的 99.98%。iOS 保持在 99.95% 目标之上。我们还加了自愈流程,让 Agent 能自动发现并修复崩溃。

而且 App 现在已经为 Agent 就绪:每个屏幕的 state 和 action 都通过可内省的 ViewModel 暴露出来。借助 Reflex 架构和 CLI,Agent 不用启动模拟器就能测试大部分 App,Shopify 里任何人都可以用 River 构建并验证一项移动端改动。

这就是我们想要的结果:给商家一个更快的 App,也给人和 Agent 一个更容易持续改进、持续协作的代码库。

§ 25

A few things we would tell a team starting down this path:

  • Spend the time upfront to give agents a fast way to test your app. Business logic that runs without a device and the Reflex architecture with the CLI to drive it were foundational for us.
  • Make architecture executable. If the rule matters, make it visible in examples, Architecture.md, tests, lint rules, or CI.
  • Prefer small checkpoints over big agent-generated PRs. Reliable convergence beats a perfect first attempt.
  • Use the same architecture across platforms when the product behavior is shared. Consistency is what makes agent output reviewable. This is true for both business logic and UI patterns.
  • Let agents review first, but keep humans as the final decision makers.
  • Treat review capacity as a real system constraint. The diff size a human can understand should shape the work you give to agents.
  • Expect the bottleneck to move. When code gets faster, machines, CI, review, merging, and coordination become the next constraints.
  • Be explicit about ownership. When work moves faster than tickets, unclear ownership turns into duplicate work.

The clearest lesson from us is this: Now that agents can write a lot of the code, engineering judgment moves to the pieces around those agents: the architecture they follow, the feedback loops they use, the checks that fail when they drift, the review process that decides what ships, and the ownership model that keeps people from stepping on each other.

That is what we rebuilt. Not just the mobile app itself, but the way we built it.

So, is our app vibe coded? No. In fact, our code has never been more consistent with our desired patterns. We spent a lot of time crafting the right architecture and putting guardrails in place so agents generate code with the shape we want.

Agents do not magically produce good or bad software. They amplify the environment you put them in. The product is still the result of the patterns you choose, the architecture you design, the checks you enforce, and the judgment you apply before anything ships.

Everything here might look outdated in a few months. When it does, we will share what changed.

如果团队要走这条路,我们会说几件事:

  • 前期花时间,给 Agent 一个快速测试 App 的方式。业务逻辑不依赖设备就能跑,加上 Reflex 架构和驱动它的 CLI,这是我们的地基。
  • 让架构可执行。规则重要,就让它在示例、Architecture.md、测试、lint 规则或 CI 里看得见。
  • 宁可要小 checkpoint,不要 Agent 生成的大 PR。可靠地收敛,胜过第一次就完美。
  • 产品行为共享时,跨平台用同一套架构。一致性让 Agent 的产出可评审,业务逻辑和 UI 模式都是如此。
  • 让 Agent 先评审,但最终决策权留给人。
  • 把评审能力当成真实的系统约束。人能理解的 diff 大小,应该反过来决定你交给 Agent 的工作。
  • 预期瓶颈会移动。代码变快之后,机器、CI、评审、合并和协调就是下一批约束。
  • 把归属说清楚。工作快过 ticket 时,归属不清就会变成重复劳动。

我们最清楚的教训是:既然 Agent 能写大量代码,工程判断就转移到了 Agent 周围的东西上——它遵循的架构、它使用的反馈回路、它跑偏时会失败的检查、决定什么能发布的评审流程,以及防止人们互相踩脚的归属模型。

这就是我们重建的东西。不只是移动 App 本身,还有我们构建它的方式。

所以,我们的 App 是 vibe coding 出来的吗?不是。事实上,我们的代码从未像现在这样贴合想要的模式。我们花了很多时间打磨合适的架构、放好护栏,让 Agent 生成我们想要的形状。

Agent 不会凭空产出好软件或坏软件。它们会放大你给它们的环境。产品仍然是这些选择的结果:你选定的模式、你设计的架构、你执行的检查,以及发布前你施加的判断。

这里的一切几个月后可能就显得过时了。到时,我们会分享发生了什么变化。

Open source ↗