Wolfia logo
Help

All aboard the mobile release train

How to ship higher quality apps by adopting continuous deployment

Fabien

February 16, 2023

Photo by Brian Suman on Unsplash

What are mobile release trains?

A mobile release train is the concept of shipping an app at regular intervals, ideally every week, independently of feature development and feature readiness. This is the closest we can get to Continuous Deployment on mobile.

mobile-release-train

In other words, every week, at a fixed time, the train (the release) is leaving the station. You’re either onboard (your feature has been merged) or you’re not: too bad, but no worries, just catch the next train!

mobile-release-train-schedule

In the above example, 3 features made it into v1.0, but the next one (feature 4) wasn’t merged in time and will have to wait for v1.1. It’s not a big deal as long as the release cycle is short.

Feature flags

You might have already noticed a problem with this concept: in practice, we don’t want to wait until a feature is complete to merge it. Instead, we would like to have small, independent pull requests that are easy to review and are unlikely to create conflicts. How to deal with that issue? Enter feature flags.

mobile-release-train-feature-flags

Each new feature should be behind a feature flag: this is a check that tells us if the feature is ready for public release. If the feature is not ready, we display the old UI to the user, or we hide the entry point of the feature. If it is ready, we display the new feature.

if (features.feature1.isReady) {
  // show new UI
} else {
  // show old UI
}

Feature flags are a requirement for adopting release trains, but one could start with a simple list of flags (booleans) hardcoded in the code! No need for a complex system to get started. One simple solution is to turn all feature flags on if the user’s email domain is your company.

if (user.email.endsWith("@mycompany.com")) {
  for (feature in features) {
    feature.isReady = true;
  }
}

Another option is to turn it on based on whether the build is an internal build or a production build.

Branching strategies

A question people often ask is whether they should have a release candidate branch. The idea is to create a branch “Release candidate v1.0” that you then test, and fix bugs on, before releasing. That technique can work fine if you are moving slowly and rely mostly on manual QA, but it’s not ideal.

Once you’ve fixed the bugs on your Release Candidate branch, you will have to merge those fixes back into your main one. You can either cherry-pick the fixes one by one, or merge the whole branch back. But if you have developed a lot of new code on your main branch since then, you’ll have to deal with conflicts.

release-candidate-branch

A better strategy is to instead adopt the policy that main is always stable. Meaning that you should always be able to ship your main branch at any time. Obviously, automated tests are a big help here, but if you use feature flags, you will still be able to test a new feature manually before it’s released. Simply don’t flip the switch until you’re satisfied that the feature works as intended. You can send a version of your app with the flag turned on to whoever is going to test it.

Main benefits

This technique is used at scale by most tech companies like Uber, Shopify, Lyft, and many others.

The main reasons are:

  • Predictability: no need to ask when the next release is going to be, it’s always at the same time. This helps both engineers and product managers.
  • Speed: this method allows teams to ship new features and bug fixes very frequently without having to worry about the state of the other ones.
  • Quality: the discipline that comes with keeping main always stable, along with not having to rush your feature in the monthly release, leads to higher app quality.
  • Scale: this method scales to an arbitrarily large number of engineers working on the same app. No need to synchronize different teams’ schedules, or worry about merging.

Release philosophy

To recap, here are the main properties we would like our release strategy to have:

  • The release train leaves the station at a fixed time, every week, no matter what. If your feature didn’t make it in, it’ll have to catch the next train.
  • The main branch is always stable, and therefore always shippable.
  • Any new feature is developed behind a feature flag, the feature flag is only turned on once we are satisfied that the feature is ready.

One key component to achieving this is automation:

  1. It enforces that the train leaves the station on time: teams can’t ask the driver to wait for them.
  2. It saves engineers a lot of time: that time is better-spent building features rather than managing releases.

Wolfia can set up a Release Train for your app automatically, contact us if you’re interested!