---
title: "Why MoneyMama builds on Expo and ships through Codemagic"
description: "We avoided Expo on Hargapedia for years. The MoneyMama app is built on it, and every build goes out through Codemagic rather than EAS. Here's why both changed."
url: "https://rayson.me/writing/expo-and-codemagic/"
category: "Engineering"
author: "Janarayson"
published: 2026-09-24
---

The MoneyMama app is built on Expo, and every build goes out through Codemagic rather than Expo's own build service, EAS.

Neither of those was an obvious choice for me. On Hargapedia, we stayed away from Expo for years.

## Why we avoided Expo before

My impression of Expo back then wasn't great. Bare React Native gave us a lot of flexibility: you owned the iOS and Android projects and could do whatever you needed in them. The first Hargapedia app in 2018 was bare React Native, and so was the rebuild in 2024.

That flexibility came with its own problems later on. When React Native started moving to the New Architecture, a lot of the libraries we depended on weren't ready for it, and in a bare project, that's all yours to sort out.

There's no going back now either. React Native 0.82, released last October, was the first version that only runs on the New Architecture.

## What changed

Expo is a different animal today. React Native's own documentation tells you to start a new app with a framework, and the framework it names is Expo. The developer experience is much better than I remember.

The MoneyMama app started in July on Expo SDK 57, with the New Architecture and Hermes on from the first commit.

The iOS and Android folders aren't in the repository at all. Every build generates them fresh from app.json using prebuild, so app.json is the one place the native configuration lives, and anything native we need is added as a config plugin. Nobody has to remember to regenerate the native projects after a change, and nothing stale gets shipped because somebody forgot.

## Choosing a build service

Expo has its own build service, EAS. We set it up for about a week in August and never ran a single build on it.

The one part of EAS we kept is push notifications, because Expo's push tokens need the app to be linked to an EAS project. Everything else goes through Codemagic, which we'd been using on Hargapedia since 2021.

<Figure
  src={codemagicLogo}
  alt="The Codemagic logo"
  small
/>

Mostly, the free tier did the maths for us.

EAS's free plan gives you 15 Android and 15 iOS builds a month, in a low-priority queue, with a 45-minute limit on each build. Codemagic's free plan gives you 500 minutes a month on M2 Mac minis, with up to two hours per build.

<Figure
  src={easFree}
  alt="Expo's pricing page, the Free plan: $0 a month, 15 Android and 15 iOS builds, low-priority queue"
  caption="Expo's free plan, October 2026."
  small
/>

<Figure
  src={codemagicFree}
  alt="Codemagic's pricing page, the plan for individuals: 500 free macOS M2 minutes a month, max 1 parallel build, unlimited applications"
  caption="Codemagic's free plan for individuals, October 2026."
  wide
/>

Our builds take about 15 minutes on average. That works out to around 30 builds a month, which is more than enough for us, and we're still on the free plan. Codemagic's free tier only runs one build at a time, but we have no need to run them in parallel.

Expo's own round-up of CI tools, which you'd expect to favour EAS, describes Codemagic's iOS code signing as "well implemented" and its pay-as-you-go pricing as "easy to reason about". That matched our experience.

## What a release looks like

The whole pipeline is a codemagic.yaml file in the repository, with one workflow for Android and one for iOS.

Pushing a git tag starts a build, and the tag has to match the build number in app.json. Before it builds anything, the pipeline asks Google Play and TestFlight for the latest build number they already have, and stops if ours isn't ahead. Otherwise we'd wait 15 minutes for a build the store would reject on upload.

Then it runs prebuild, signs, builds, and uploads to Play's internal testing track and to TestFlight. Pushing a build out to everyone is still a button I press in each store's console.

## The one thing that caught us out

Codemagic's Android signing hands you the keystore as environment variables, but it doesn't touch build.gradle. And prebuild throws build.gradle away and writes a fresh one on every build.

So we have a small script, with its own tests, that patches the signing configuration back into the regenerated file each time. It looks for exact lines from Expo's template, and if Expo ever changes that part of the template, the script fails the build rather than guessing where the lines should go.

## No over-the-air updates

We don't do over-the-air updates. Every change, even a one-line JavaScript fix, goes out as a store build and reaches users when they update.

That's a lot of builds, which is why the build minutes mattered more to us than anything else on the pricing page. For now, the free plan covers it.
