Versioning mobile app releases like a pro

When and how to increment your version numbers

We all know that a project should have a version number. When you release new features, you should increment your version number, right? But exactly when in the development process is that? And how do you keep track? This article describes the simple strategy that I use across our mobile app projects at Control F1.

Aims of versioning

Before getting to the when and how, let’s start with why. My main aims are that:

  • Everyone should know what version of the app they have if they are reporting bugs or requesting support

What is a version number

A version number has three components, major.minor.patch e.g. 1.2.13. You decide which to increment based on the changes you have made since the last version.

  • minor is for new functionality
  • major is for major changes, like a rewrite of the project

Setting the version number in your project

In iOS it is set in the Version field in the General tab of your app’s target properties.

Version field in an iOS project
Version name in an Android project

Display the version number in your app

In order for everyone to know what version number of the app they have, you need to display it to them in your user interface. The home screen, main menu or an information screen can all be good places to put it.

Version number displayed in an app

Track which features go into a version

Start by creating a placeholder for your next release version. This can be as high-tech as a fix version in JIRA, or as low-tech as a note on a piece of paper.

Build a release

I’m using release to mean the process for packaging up an app to give to some or all of your everyone. For android you’ll create an APK, and for iOS you’ll create an IPA. When you build a release, you bake in your features, and you also bake in your version number.

  1. Build the release
  2. Commit your version number changes and tag in source control with the version number

Create release notes for your users

For everyone to know what features are available in a given version of the app, you need to provide them with release notes. We make different versions depending on the audience, but as an example we’ll do the following.

  • For beta testers and users, we compile a non-technical, easily understandable report. They might not get every single release, so we make sure to include everything that has been added since the last version that was made available to them.

A note on accessing code for old versions of your app

In the not too distant past, another important aim of versioning was to allow you to access code for old releases. Releases were few and far between, and different versions of the same software were supported at the same time. Bugs had to be fixed and patched in a particular version, which made it important for you to be able to lay your hands on the source code for that release. Now that releases are frequent, and generally only the latest software version is supported, it’s very rare to go back to an old version. In fact I can’t remember the last time I patched a release.

A note on build numbers / version codes

As well as a version number, iOS apps have a build number, and Android apps have an equivalent version code. This is a single number that identifies a particular build, and the app stores require that it must always be higher than the last one when you submit a build. They don’t have a special purpose in my workflow, so we simply increment them at the same time as the version number.

Other strategies and why I don’t use them

Photo by Branden Tate on Unsplash

Build numbers / version codes

To indicate that a new release only includes a very minor change or fix, some teams might only increment the build number. This is sensible, but we don’t use it because version numbers increment automatically in our release process, and we’d have to intervene to stop that happening.

Tracking features in versions after you release

In my workflow, we create a placeholder version after the release, and we add versions to features as soon as they are developed. You could wait until after you’ve built the release, get its actual version number, and then go back and tag all the features that went into that release. I used this approach for a while, but found a couple of drawbacks. With my workflow, if you use a system like JIRA to track your releases, you can see how your release is shaping up as you go. You lose that if you don’t version features as they are completed. I also found it to be more of an administrative burden to wait until the release. You have to find all features that have been finished but not released, and you have to tag them all at once.

Incrementing versions after the release

In my workflow, the version number is incremented before the release is built. I have seen workflows where it is incremented immediately afterwards instead, in preparation for the next release. That’s not a good idea because you can have builds that don’t contain the features you expect them to. Let’s say you’ve incremented your version to 2.5.3 and you’ve built it to a device. Then you add more features and tag those, but the build on that device never gets updated. The app says its version number is 2.5.3, but it doesn’t contain the features it should. That can’t happen if you increment just before you build the release.

Alpha, beta, RC, GA etc

Sometimes you see releases labelled with the version number plus alpha, beta, RC (release candidate), GA (general availability) or similar. There are two reasons why I don’t use this. First is that it’s unnecessary in my workflow. When a release is built, it is sent for internal testing. If it passes internal testing, it will be made available to beta testers. If it performs well in beta testing it will be promoted to the app store. If it fails at any of these stages, it won’t progress any further and the process starts again with the next build. You can tell the status of the build by where it is in the process, you don’t need the tag to tell you. Second is that it adds extra work. It is the same build at each stage, and it would be pointless to re-build and re-version exactly the same code just to add a tag.

Commit hashes

I’ve seen apps that use the last commit hash on a branch to identify test releases of an app. This uniquely identifies the release, but gives you no information about the order in which the releases occurred. For example if you have a feature that was added in version 1.3.4 and you have version 1.4.1, you know it is included. However if it was added in version 9a10ea01, you have absolutely no idea if it should be available or not in version 13be2fc4.

No versioning

I’ve been unfortunate enough to work on projects that didn’t use any versioning, at least until after the testing stage. If you’ve ever tried to figure out why something isn’t working when it should be, or seen the frustration on a test engineer’s face as you realise that you accidentally gave them an old build, you’ll know where I’m coming from. If you haven’t, trust me, don’t go there.


In this article I’ve described what I want out of versioning, the strategy I use to achieve it my mobile app projects, and why I’ve chosen not to use some alternative approaches. I hope you have found it useful.

Mobile app strategy and development. Principal Consultant at @InfinityWorks and creator of @Tasktimerappuk and Windsurf Caddy

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store