Mobile Version Checking at FlightAware

Mobile Version Checking at FlightAware

Managing multiple versions of an app is crucial to ensure that users have a smooth experience and that the app functions on different platforms. However, running into issues is not uncommon, especially when changes to backend services or other essential factors make previous app versions obsolete. Furthermore, it is important to keep users informed about available updates, including any requirements such as device upgrades or operating system updates.

Recognizing the need for a service that could handle app lifecycle management, our team developed a solution with two primary objectives. The first objective was to ensure that users always use the latest version of our app, with bug fixes and updated features. The second objective was to have the ability to retire backend services and old app versions without abruptly cutting off users, which would result in a poor user experience.  This blog post will focus on how we created this solution and how we integrated it into our app.

Updating and Maintaining Version Data

Our solution is a combination of a service called Mobile Version Check and logic to process that in the client-side app UI. The service oversees updating and maintaining our app version data as well as determining if a user needs to upgrade to a new version based on input that is provided. It is accessed through a REST endpoint and is deployed on two Kubernetes clusters using Flux. Each deployment includes two replicas that check independently to ensure that they are up to date with Apple’s App Store Connect API. This is a tool that allows developers to retrieve specific details about apps, such as the app’s version number, release date, and other details by using an app’s unique ID or URL. The service periodically checks this API to maintain a history of our app releases and compatible devices for each app version. A successful response may look as such:       

This response tells us what the current running version of our app is, when it was released, its minimum OS version, and the devices that can run it. These responses are then saved for later reference into our app version file. This file is set to be updated every 15 minutes, when a new app version is released, or a new Apple device is released. After an update, each pod replica will restart and purge the cache. 
In addition to this data, there is a JSON file embedded in the service’s Go binary. It is manually curated by developers and is updated directly in the project after Apple product releases or as needed. This file is responsible for keeping track of the minimum allowed version of our app that users can have installed on their devices. This is how the service determines if we need to require an update from our user. 

All this data makes up the instructions for how the service will respond to a version check when queried.

Querying the endpoint 

Here’s a breakdown of how the service gets queried:


  • app_identifier: Unique identifier for the app
  • app_version: Current version of the app
  • os_version: Operating system version
  • device_model: Model of the device

When a query is made to the endpoint, the parameters that are sent with it will be checked against the rules that have been set up using Open Policy Agent configuration files. This library can evaluate and interpret the configuration files, as well as the device and app version information provided. Based on this, the service will then determine whether the current app version is still supported and if an upgrade is available for the device.

A JSON-encoded response then gets returned. It contains flags indicating if an upgrade is required and any additional fields for upgrade information such as the newest version they can upgrade to, and the minimum OS version needed for the upgrade. 

Multiple variations of responses get returned based on the data used to query the service. 

Here are some examples of what we may get back.

Example 1: A response for a user running the latest app version with the newest OS: 

This tells us that the user does not have any upgrades to make and will not have to update their app. They are on the most up-to-date version of our app.


Example 2: A response for a user that is running an older version of the app that is not required to update.  

In this case, we would notify the user that they can choose to upgrade their app version without needing to update their OS to do so.

Example 3: A response for a user that is currently using a discontinued version of our app and needs to upgrade to the newest version before they have access to our app again.

This lets us know to force the user to upgrade to the latest version of the app, and that no OS update is required to do so.

All of these are possible responses that will be sent directly back to the client-side app where they will be used to determine if or what screen appears. 

Prompting upgrades in the app

The client-side app checks for new updates from Mobile Version Check on each app launch. It provides the current device model, operating system version, and the app version that the user is currently using to get the update. If there is no new version available, the app can continue to function normally.

Two types of screens may be presented when a new update is available. First, the user might be running an older version of the app that is not required to update, but we have additional update fields populated for them. In this case, the app will display a popup with options (using a client-side algorithm for timing and frequency of presentation), which can be dismissed to continue using the app.

Second, if the user is running an app version that has been discontinued, the app will prevent them from using its features. This is signaled by "”upgrade_required”: true". In such a case, a non-dismissible full-screen message will be presented, which includes a link back to a page on that explains the policy and why this has happened.


The implementation we have adopted has not only helped us to efficiently manage the lifecycle of our product but also made it easier for us to maintain both front-end and back-end code bases. Furthermore, it has provided our customer support team with a clearer support matrix by reducing unnecessary report requests and simplifying knowledge base management.

Samantha Turnage

Samantha Turnage

As a Software Engineer on FlightAware’s Mobile team, Samantha Turnage works to refine and maintain the FlightAware iOS app.

Show Comments
Back to home