Field Manual - Log EntryVol. 01§V · Entry2 min read

react-native-to-expo-what-i-would-do-differently.md

§V · ENTRY

by 2 min read

I chose bare React Native on purpose, and I'd choose differently now

In 2023 Expo couldn't do the native work an2 cabs needed, so I went bare. Three years on I'm shipping two Expo apps. What changed wasn't my reasoning, it was the platform.

I have shipped mobile apps both ways. Bare React Native at an2 cabs in 2023, and two Expo apps at AfterBoards since. People tend to ask which one is better, which is the wrong question. The interesting part is that the same reasoning produced different answers three years apart.

Why I went bare in 2023

Going bare was my call, and it was not reluctant.

The an2 cabs apps needed native capability that Expo could not reach at the time:

  • Background GPS tracking. A driver app that stops reporting location when the OS suspends it is not a driver app. This is the hardest thing on the list and the least negotiable.
  • Floating notifications. Ride requests that surface over whatever the driver is currently doing.
  • Other native modules that had to be linked directly into the React Native build.

In 2023 the managed Expo workflow could not do this. Ejecting was the documented answer, and ejecting-later is a worse position than starting bare, because you inherit a generated native project instead of one you understand. So I started bare and kept full control of the native side.

That decision was correct. I would make it again given the same information and the same year.

What changed

Expo development builds.

The old trade was framed as all or nothing: take the managed workflow and accept its native ceiling, or go bare and own Xcode and Gradle yourself. Development builds broke that framing. You can now add custom native code and third party native modules while keeping the managed workflow, EAS Build, and over-the-air updates.

The constraint that pushed me to bare in 2023 is the exact constraint that no longer forces the choice.

What it costs to be bare

None of this is theoretical. Owning the native project means owning:

  • Xcode and Gradle upgrades, on their schedule rather than yours
  • native dependency conflicts, resolved by hand
  • signing and provisioning, forever
  • a React Native upgrade path that touches native files you have edited

On a team with people to absorb that, it is a real cost paid for real control. Alone, it is a tax on every release. At AfterBoards I am the only engineer on two mobile apps, and the calculation is not close.

The part that generalises

The thing worth taking from this is not "use Expo."

It is that a tooling decision has an expiry date, and it does not announce it. My reasoning in 2023 was sound: I listed the native requirements, checked whether the managed workflow could meet them, found it could not, and chose accordingly. Every step of that was right. The answer still went stale, because the platform moved underneath a constraint I had treated as permanent.

The failure mode is not making the wrong call. It is making the right call and then never revisiting it, so that three years later you are still paying for a constraint that quietly stopped existing. The reasoning is worth writing down precisely because it lets you check later whether the premises still hold.

So: default to Expo now. But keep the list of why, because that list is what tells you when the default has changed again.

--faq --questions

§V · Q&A
Should I use Expo or bare React Native for a new app?
Start with Expo. The old reason to go bare was custom native code, and development builds removed that constraint. Bare is now a deliberate escape hatch rather than a starting point.
Why would anyone still choose bare React Native?
When you need control over the native build itself rather than just the ability to add native modules. That is a much smaller set of projects than it was in 2023, and worth confirming you are actually in it before committing.