Incremental Mobile Force Update using Ingress NGINX and Firebase Remote Config

Mobile force updates occur when old versions of an app are no longer compatible with the APIs they consume. Until the app is updated to the required version, the UI blocks further usage. This is usually materialized as a system popup that will redirect users to the respective Store and disappear only once they have updated to the latest version. This is often considered bad practice as it deteriorates the UX of an app drastically, yet there are situations (mostly breaking API changes) when it is unavoidable.

Such updates are quite risky, as once an app is updated in the stores, there is no going back unless the previous version of the app is released again under a different version number. Web applications do not face such risks as they are easily rolled back. Also, just like for backend APIs, a web app can incrementally roll out such changes using a canary deployment.

If you haven’t already, go read Canary Deployment in Kubernetes (Part 1) — Simple Canary Deployment using Ingress NGINX and learn how to implement a Simple Canary Deployment using Ingress NGINX!

However, this doesn’t mean that there are no solutions. In fact, it is possible to leverage backend canary deployments in order to incrementally roll out a mobile force update. Ingress NGINX, for instance, only provides traffic splitting based on canary-weight but it also features traffic routing based on canary-by-header which can be used for this purpose.

What if we could route user traffic based on the version of the app they are using?

🎬 Hi there, I’m Jean!

In this article, we’re going to learn how to leverage a simple canary deployment using Ingress NGINX and Firebase Remote Config to safely conduct an incremental mobile force update! 💪

Smart Traffic Routing with Firebase Remote Config


Firebase Remote Config is a powerful Cloud service from Google that enables frontend applications to store their configuration properties in Google’s Cloud and access them remotely via a dedicated Firebase SDK (available in iOS, Android, C++, and Javascript).

While editing those configuration properties would normally require a frontend release, with Firebase Remote Config, developers can simply change the properties values in Firebase’s UI and the frontend will update itself automatically on the fly.

The most powerful feature of Firebase Remote Config though is that configuration properties can have dynamic values, based on app data (or even user data from Google Analytics). 🤯

For instance, say we must make a non-backward-compatible change to our Backend API, this means all our mobile apps must conduct a force update. Thus, if users are using version v1, they will be prompted to update their app to version v2 so that they can keep on consuming the Backend API. But what if this non-backward-compatible change is a faulty one? How do we revert such a change? Well, in fact, we can’t: once a user has updated their mobile app, there is no going back. So how do we solve this then?

Well, to solve the force update problem, we could theoretically define a Remote Config called UseCanary and give it a dynamic value based on the app version.

Specifically:

  • If AppVersion < 2.0.0, UseCanary = never;
  • If AppVersion ≥ 2.0.0, UseCanary = always.

Then, when the app fetches its Remote Config, it can add to its requests the famous X-Canary header we talked about in Simple Canary Deployment using Ingress NGINX (remember? 😉) like so: X-Canary: <UseCanary>.

This will result in:

  • If AppVersion < 2.0.0, request header = X-Canary: never;
  • If AppVersion ≥ 2.0.0, request header = X-Canary: always.

In Firebase Remote Config, this is called a condition. A condition is a logical block allowing Remote Config properties (called parameters) to have dynamic values based on various app or user data, such as the app version.

Firebase Remote Config

Then, creating a dynamic parameter simply boils down to specifying its name, condition(s), and associated values.

Firebase Remote Config

Now we made sure that only users using the v2 version of the app get routed to the canary deployment, we can roll out our non-backward-compatible change to canary and start doing some smoke tests, in complete isolation from the rest of the userbase!

Incrementally Rolling Out Mobile Releases


Once ready to go live, the mobile engineering team can start incrementally rolling out their new v2 version of the app in the stores:

As users update their app, traffic to the canary deployment will start coming in and if things suddenly go south, the Phased Release or Staged Rollout can be easily paused, until a fix is deployed to the canary deployment.

Incremental Force Update Rollout

Once the rollout of the non-backward-compatible change in canary is considered successful, the mobile engineering team can proceed with the actual force update and the stable deployment will soon stop receiving traffic altogether. This means that all users have now migrated to the v2 version of the app, the canary rollout is therefore complete and can be rolled over to the stable deployment!

Wrapping up


To summarize, using Ingress NGINX in tandem with Firebase Remote Config, we were able to:

  • Route user traffic to a canary deployment based on the version of the app they are using;
  • Incrementally rollout a non-backward-compatible change to minimize risk before conducting a force update.

Was it worth it? Did that help you understand how to incrementally conduct a mobile force update using Ingress NGINX and Firebase Remote Config?

If so, follow me on Twitter, I’ll be happy to answer any of your questions and you’ll be the first one to know when a new article comes out! 👌

Bye-bye! 👋