⚡ LIVE From Lizard to Wizard · Thursday, May 28 · LIMITED SEATS Save my seat →
Episode 35 60 minutes

React Native at Scale with Kadi Kraman

Key Takeaways from our conversation with Kadi Kraman

Kadi Kraman

Software Developer at Expo, ex-Formidable React Native Engineer

Señors @ Scale host Neciu Dan sits down with Kadi Kraman, software developer at Expo working on the tools that make React Native development as smooth as possible. Kadi's path started with C++ in a university maths degree, took her through Angular 1, scientific programming for pharmaceutical and defense companies, five and a half years at Formidable, and finally to Expo itself. From the limitations of early React Native to development builds, EAS workflows, fingerprint-based repacks, and the right way to think about over-the-air updates, this is the React Native conversation most web developers never get.

🎧 New Señors @ Scale Episode

This week, I spoke with Kadi Kraman, software developer at Expo, where she helps build the tools that make React Native development as smooth as possible. Kadi has over six years of hands-on React Native experience and has worn almost every hat in engineering — IC, mentor, manager, technical lead, and director — before joining Expo to work on the platform itself. Her first code was C++ in a university mathematics degree, and a chance Hacker News post landed her in the React community in London, then at Formidable for five and a half years, and now at Expo.

In this episode, we dig into why React Native today is faster and more performant than building with Xcode and Android Studio directly, how Expo replaces the entire native build pipeline, what changed when development builds replaced Expo Go for production, and the right way to think about over-the-air updates without getting your app pulled from the store.

⚙️ Main Takeaways

1. React Native today is faster and more performant than native for most apps

The early limitations are gone. Kadi pushes back hard on the idea that native is still the better experience.

  • The hot reload gap: Building native iOS or Android in Xcode and Android Studio requires a full rebuild to see UI changes — significant time on a big app. React Native gets hot reloading for free because the JavaScript bundle reloads while the native shell stays put.
  • The same components underneath: "Using React Native to build your native app is faster and more performant and a better user experience than just using Xcode and just using Android Studio." You're still rendering the same native components — just driving them from JavaScript.
  • The architecture jump: The new architecture finally shipped after years in the works, closing most of the historical performance gaps between the JS side and the native side.

2. The hardest mental shift coming from the web is styling and pixel density

Coming from React on the web, the biggest mental rewiring is around layout, units, and inputs.

  • Inline styles only: There's no CSS — you basically have inline styles, no cascading, no media queries the way you're used to.
  • Display points, not pixels: When you write width: 100, that's not pixels. It's display points. An iPhone has a pixel density of 3, so one display point is 3×3 = 9 actual pixels. An older Android might be 1.5 or 2. Image strategy depends on this.
  • Gestures and touch surfaces: On mobile you have to think about swipes, swipe-up, swipe-down, and the fact that a tooltip rendered under the user's finger is invisible. Kadi wrote a long Expo blog post called From Web to Native with React covering all of this.

3. Expo is to React Native what Next.js is to React

The single sentence that frames everything else.

  • The framework analogy: "Expo is to React Native what Next.js is to React." React Native core is intentionally lightweight — it doesn't ship navigation, push notifications, video, audio, bottom tabs, or deep linking. Meta focuses on the JS-to-native bridge and the new architecture.
  • What Expo gives you: A multitude of libraries, convenience functions, CNG (Continuous Native Generation) that auto-generates the iOS and Android directories from your config, EAS for build signing, and Expo Router with API routes you can deploy alongside the app.
  • The alternative is exhausting: Without Expo, every decision — "I need to play video" — sends you to React Native Directory, ten libraries deep, asking which one is still actively maintained. Expo provides most of those out of the box and a template for writing your own native bindings when you need them.

4. Expo Go is now just for learning — development builds replaced it for production

The shift from Expo Go to development builds was the big architectural change.

  • The old model: Expo Go shipped with all the native code you might possibly need. You wrote only JavaScript and ran it inside Expo Go. The pain hit the moment you needed something not in Expo Go — Firebase auth, payments, deep linking to a custom domain — and you had to switch tracks entirely.
  • The reputational damage: People assumed Expo was just Expo Go and therefore only useful for learning. Anything serious required dropping it.
  • The new reality: Expo Go is now branded explicitly for learning and prototyping. For real apps you use development builds, with CNG handling iOS and Android directories, EAS handling build signing, local builds available, and easy build sharing across the team. "There isn't a thing like 'I need to do this library, but it might not work in Expo.' That doesn't exist anymore."

5. EAS Workflows, repacks, and fingerprinting

The CI/CD primitives that make build pipelines actually pleasant.

  • Custom environments: Beyond development, preview, and production, you can name your own environments with their own environment variables.
  • Workflows: Define jobs that run on PR, on tag, on label — lint, tests, Maestro tests. Configurable per project.
  • Repack jobs: If you've only changed JavaScript, you don't need a full native rebuild. Repack rebuilds just the JS bundle and drops it into the existing native shell. Much faster than a full rebuild.
  • Fingerprinting: Every build calculates a project fingerprint — a hash of all native files and your app config. If only JS changed, the fingerprint matches an existing native shell, and the workflow uses repack. If native changed, fingerprint differs and a full rebuild kicks in.

6. What React Native and Expo still struggle with

Kadi was direct about the open problems.

  • Web story: React Native for Web is still undecided. Commitment issues — you don't know what its future looks like.
  • Styling overhaul: There has been ongoing work to make styling more web-like for a while, but it's a big change taking time.
  • CocoaPods has to go: React Native needs to move off CocoaPods, likely toward Swift Package Manager. Still an unsolved migration.

7. Performance lists and the developer's role in performance problems

A lot of "React Native is junky" complaints are actually self-inflicted.

  • The shoot-yourself-in-the-foot pattern: "Some of the times developers, when we're having performance issues, we're the ones shooting ourselves in the foot." Rendering a list where each item is a complex component with hundreds of sub-components will never be performant.
  • The list options: The built-in list has improved. Shopify's FlashList is good, especially for image-heavy lists. Legend List is the new JavaScript-only implementation that's clever about reusing already-rendered components instead of rendering 20 items on each side.
  • The compiler: React Compiler optimizes re-renders and reduces unnecessary ones — performance gains for free.

8. Debugging crashes that only happen in production builds

The frustrating "works in Expo Go, crashes in TestFlight" moment.

  • The most common cause: You're relying on a native library that's in Expo Go but not in your package.json. Build a native app and it crashes immediately because the library isn't there.
  • The second cause: Environment variables. Library crashes without them, and you forgot to add them to the production build.
  • Run expo doctor first: npx expo-doctor checks your project for common issues — missing libraries, missing config plugins, accidentally committed native projects, bundling issues. "Run expo doctor and make sure you don't have any warnings." A lot of the time that fixes it.
  • Last resort: Plug your phone into a Mac and read native logs — Console.app for iOS, logcat in Android Studio for Android. Feed those logs into Claude — they're indecipherable on their own, but an LLM is "pretty good using someone else to explain the logs for you." Kadi has debugged native crashes (memory mismanagement, weak reference issues) this way.

9. Over-the-air updates: a superpower with a gray area

OTA updates are a React Native superpower that native developers don't have, but they're easy to misuse.

  • How it works: The app ships with a Hermes bytecode JavaScript bundle. With EAS Update, you publish a new bundle, the device fetches a manifest from the Expo service, downloads the new bundle, and uses it on next launch instead of the bundled version. Same native app, updated JS.
  • The right use cases: Testing (Kadi uses it constantly for her own apps in TestFlight) and critical bug fixes — broken form validation blocking sign-up, broken checkout. Push the update, then ship a follow-up native build that fixes it from first install.
  • The terms-of-service gray area: Both iOS and Android stores allow interpreted code, but they don't allow you to change app behavior in a way that would have required re-review. Shipping whole new features via OTA isn't allowed.
  • The conservative take: "I would rather have an app that has the bundled JavaScript module rather than an app that has an updated module." Updates add the cost of downloading and refreshing, and store users get a different version than update users.

10. React Native for Brownfield: dropping React Native into existing native apps

You don't have to rewrite the whole app to ship React Native.

  • The use case: Add a single React Native screen, view, or entry point to an existing native iOS or Android app. Kadi calls this brownfield — a native app without React Native that gets React Native added to it.
  • The new support: From SDK 55, Expo has a built-in way to do this very easily.
  • The hidden benefit: OTA updates on just that React Native part of an otherwise fully native app.

11. Career advice: apply when you're 70-80% qualified

Kadi's advice that applies to women more than men, but applies broadly.

  • The pattern: Women look at a 10-item job spec, find one item they're not 100% sure about, and disqualify themselves. Men typically don't.
  • The reframe: "That list is not set in stone. You might be bringing so much more to the table that's not on this list, that will compensate on this random thing some hiring manager put together because he needed a list of 10 items."
  • The same logic for talks and workshops: "People wouldn't have asked you if they didn't think that you would be a valuable person for this opportunity." Just give it a go.

12. How to find a talk topic when you have impostor syndrome

The advice for first-time speakers.

  • Pick something specific you actually dug into: Kadi cites two talks at App.js by Delphine (now at Mistral). One was about a Yoga bug where text overflows the screen and flex: 1 fixes it. The other was about why you can't stream text in React Native — fetch is built on XMLHttpRequest under the hood, which doesn't support streaming, so you need a polyfill like Expo Fetch.
  • The principle: A bug you encountered, dug deep on, and got excited to tell your colleagues or partner about — that's the great talk topic.
  • The bonus discovery for me: I'd just published an article on streaming and didn't know React Native couldn't stream by default. Expo Fetch is the answer.

🧠 What I Learned

  • React Native today is faster and more performant than building with Xcode and Android Studio directly, mostly because of hot reloading and the new architecture.
  • Display points, not pixels — your width: 100 is multiplied by the device's pixel density (3× on iPhone, 1.5× or 2× on older Android).
  • Expo is to React Native what Next.js is to React. React Native core ships none of the things you actually need (navigation, video, push, deep linking) — Expo does.
  • Expo Go is now just for learning. Development builds replaced it for production work, with CNG, EAS, and easy team sharing.
  • EAS Workflows let you wire up CI/CD with custom environments, test runs on PR, and repack jobs that skip native rebuilds when only JS changed.
  • Fingerprinting hashes native files plus app config — same fingerprint means a repack works, different fingerprint means a full rebuild.
  • The biggest open problems: React Native for Web is undecided, the styling overhaul is in progress, and CocoaPods needs to be replaced.
  • Most performance complaints in React Native are self-inflicted — over-complex list items, no list virtualization strategy. FlashList and Legend List are the alternatives to the built-in list.
  • "Works in Expo Go, crashes in TestFlight" is almost always a missing native library in package.json or a missing environment variable. Run npx expo-doctor first.
  • Native crash logs from Console.app or logcat are indecipherable on their own — feeding them to Claude gets you 90% of the way to a fix.
  • OTA updates are a superpower for testing and critical bug fixes. Pushing whole new features through them is against store terms of service.
  • React Native for Brownfield (SDK 55+) lets you drop a single React Native screen into an existing native app.
  • Apply when you're 70-80% qualified. Pick a talk topic from a bug you dug deep on. Both apply more to women than men in practice.

💬 Favorite Quotes

"Using React Native to build your native app is faster and more performant and a better user experience than just using Xcode and just using Android Studio."

"Expo is to React Native what Next.js is to React."

"There isn't a thing like 'I need to do this library, but it might not work in Expo.' That doesn't exist anymore."

"Some of the times developers, when we're having performance issues, we're the ones shooting ourselves in the foot."

"I would rather have an app that has the bundled JavaScript module rather than an app that has an updated module."

"People wouldn't have asked you if they didn't think that you would be a valuable person for this opportunity. You're more capable than you think you are."

🎯 Also in this Episode

  • Kadi's path: C++ in a university maths degree, scientific programming in Oxford for pharmaceutical and defense, Angular 1 with D3 and Highcharts, a Hacker News "who's hiring" post that landed her in London React, three engineers rewriting a startup platform with React Native and Expo in the very early days, then five and a half years at Formidable
  • The Expo Agent beta — a web UI for building iOS, Android, and web apps integrated with EAS, code visible alongside the prompts (like Lovable, but for mobile)
  • AI-assisted development changing the day-to-day — "this is not the job we signed up for"
  • The new mega conference NextDevCon in Berlin: four conferences in one, including a React Native track alongside Android and iOS tracks
  • AI SEO as the new community growth lever — making sure LLMs recommend React Native and Expo when someone says "build me a mobile app"
  • Linx as new competition in the cross-platform native space and why competition is good for React Native
  • Expo MCP tool and AI-assisted build log explanations in the works
  • Project Hail Mary, The Martian, He Who Fights With Monsters, Dungeon Crawler Carl, The Tainted Cup — book recommendations exchanged in both directions
  • Kadi learned English from Harry Potter as a kid in Estonia

Resources

More from Kadi & Expo:

Books mentioned:

🎧 Listen Now

🎧 Spotify
📺 YouTube
🍏 Apple Podcasts

Episode Length: 60 minutes on React Native, Expo, EAS workflows, OTA updates, debugging native crashes, and why most performance problems are self-inflicted.

Whether you're a web developer thinking about your first mobile app or a React Native engineer wondering what changed since the Expo Go days, this conversation has something immediately actionable.

Happy building,
Dan

🏆 SOLD OUT IN SINGAPORE · ATHENS · LONDON

From Lizard to Wizard

4-hour remote system design intensive.
Chat apps, microfrontends, BFF, SDUI, event-driven, observability.

€299 4-HOUR INTENSIVE
Save your seat →

Spots are vanishing. Don't be the one who waited.

💡 More Recent Takeaways

Browser ML at Scale with Nico Martin
Episode 34

Señors @ Scale host Neciu Dan sits down with Nico Martin — open source ML engineer at Hugging Face working on Transformers.js, and Google Developer Expert in AI and web technology — to go deep on running machine learning models directly in the browser. Nico breaks down architectures vs. weights, quantization, tokenizers, ONNX, WebGPU, and why on-device AI is the right answer for a huge class of problems. He also shares the road from ski instructor and self-taught web developer to landing what he calls his dream job at Hugging Face.

Frontend Foundations at Scale with Giorgio Polvara
Episode 33

Señors @ Scale host Neciu Dan sits down with Giorgio Polvara, Staff Engineer at Perk (formerly TravelPerk), who joined when the company was 15 people in two flats with a hole knocked through the wall and helped build the frontend foundations that still hold up at unicorn scale. Giorgio covers the multi-year migration from a monolithic frontend to vertical micro-frontends, why their first attempt with single-spa didn't work, how they pulled off a full rebrand behind feature flags without leaking, and the staff engineer mindset of treating every feature as a system improvement.

Module Federation at Scale with Zack Chapple & Nestor
Episode 32

Señors @ Scale host Neciu Dan sits down with Zack Chapple, CEO and co-founder of Zephyr Cloud, and Nestor, the platform engineer building it, to go deep on module federation, microfrontends, and what it actually takes to go from code to global scale in seconds. They unpack why module federation is Docker for the frontend, how Zephyr composes applications at the edge in 80 milliseconds, and why the real unlock for enterprise teams isn't deployment — it's composition.

Service Mesh at Scale with William Morgan
Episode 31

Señors @ Scale host Neciu Dan sits down with William Morgan, CEO of Buoyant and creator of Linkerd — the world's first service mesh and a graduated CNCF project. William's path runs from teaching himself BASIC on a begged-for DOS PC, through Twitter's painful migration off Ruby on Rails into JVM-based microservices, and into building the proxy that handles retries, mTLS, load balancing, and multi-cluster traffic for thousands of production Kubernetes clusters. From the Scala-to-Rust rewrite to why every sustainable cloud native open source project needs a commercial engine behind it, this is the infrastructure conversation most application developers never get to have.

📻 Never Miss New Takeaways

Get notified when new episodes drop. Join our community of senior developers learning from real scaling stories.

💬 Share These Takeaways

Share:

Want More Insights Like This?

Subscribe to Señors @ Scale and never miss conversations with senior engineers sharing their scaling stories.