Continuous Integration, Continuous Delivery, and Continuous Deployment stand as the ultimate best practices of software development automation and DevOps. However, implementing Continuous Deployment poses unique and seemingly insurmountable challenges within the realm of native mobile applications. Let's review and understand these challenges in this article.
Continuous Integration
Simply put, Continuous Integration (CI) means that team members... well, integrate their work together continuously. These days, when most software projects use Git, Continuous Integration calls for continuous merging of code changes from all team members into a single Git branch.
The actual frequency of the integration differs, with some teams aiming to integrate all their work on a daily basis, while others giving a bit more leeway to short-lived "feature branches". What everybody agrees on, though, is that a situation when team members work independently of one another for prolonged periods and then stage "big bang merge events" to integrate their contributions shouldn't happen.
It's a common practice to augment continuous integration with automated tests, static code analysis and other checks. This ensures that, at all times, the integrated code meets the minimum quality criteria defined by the team.
Continuous Delivery
Continuous Delivery (CD) builds upon Continuous Integration with the goal to have the software always ready to be released to the end users.
Practically speaking, Continuous Delivery introduces automated steps that test, build and package the artifacts following changes to the project's source code by the team members. If these artifacts should pass manual QA or be deployed to non-production environments for testing, Continuous Delivery pipeline automates these tasks as well.
The eventual result of Continuous Delivery is that the company can deploy the latest version of the software to production at any instant with a push of a button.
Continuous Deployment
Continuous Deployment is the ultimate culmination of Continuous Delivery that removes the last "push of a button" step. In other words, Continuous Deployment is when the source code gets tested, built, packaged and then deployed to production automatically, without human intervention.
While moving from Continuous Delivery to Continuous Deployment might seem relatively straightforward, it's actually a major leap. For example, Continuous Deployment mandates an exceptionally robust set of automated checks because, otherwise, deploying to production continuously would be too risky. You'll also need a very comprehensive post-deployment monitoring infrastructure to catch issues that will inevitably slip through your automated safety net.
Continuous Deployment is an exceptionally powerful practice which is often considered the ideal that all teams should aspire to. However, when it comes to native mobile apps, this ideal faces some unique challenges.
Continuous Deployment in Backend Systems
To better understand the challenges of Continuous Deployment with native mobile apps, let's review a simpler deployment scenario first: a backend application.
When deploying backend apps, you are in control over the distribution channel and the environment where the app will execute. This allows you to:
- Decide when the deployment happens precisely.
- Keep the old version of an app running in parallel with the new version, and use a load balancer to gradually steer the traffic between the two.
- Roll back to the old version if there are any issues with the new one.
- In the unfortunate event of data corruption, you have detailed information to investigate the issue, full control to fix it, and can even restore the system to the previous good state from a recent backup.
Important to note that the "rollback in case of issues" feature is important not just for technical bugs, but also for situations when a newly released version has an unexpected negative effect on the app's business metrics.
All in all, while deploying complex backend system is no joke, there are tools and practices that can make this process highly predictable, safe and, most importantly, reversible.
Continuous Deployment Challenges in Native Mobile Applications
Now let's get back to native mobile apps. Most of them are distributed through Google Play (Android) and Apple App Store (iOS), so I'll limit our discussion here to this typical scenario.
Note how the previously discussed positive aspects of backend apps' deployment are pretty much non-existent in the native mobile environment:
- You don't upload new versions of your mobile app to users' devices, but to app stores. It takes time for an app store to approve and roll out your updates. An app store can even reject an update.
- Even after a new version is available on an app store, there can be additional delays before all users upgrade to it.
- The new version of an app completely replaces the old version on the user's device, so there is no going back if they experience a critical issue.
- If there is a bug that corrupts app's persistent state, then investigating this bug can be extremely challenging because you don't have access to users' devices.
In light of these challenges, deployment of native mobile apps is a relatively long, unpredictable and irreversible process.
If a serious issue affects the new version of a native mobile app, there is no flipping a switch on a load balancer to go back to the previous version. The only way to resolve the problem is to investigate and fix the issue, upload a hotfix to the respective app store and then wait for it to propagate through all the stages, until the end users get the update on their devices. Needless to say that this issue resolution strategy can take time.
This inability to address potential problems swiftly is the main challenge of Continuous Deployment when it comes to native mobile apps. It's simply too cumbersome and risky to push out small updates continuously, when app stores stand between you and your users, and you can't do immediate rollbacks in case of critical issues.
It's worth mentioning that both app stores support staged rollouts, which let you release the updates to a subset of your users first, and then monitor the outcome and gradually increase the distribution. If there is a critical issue with the release, you can pause the rollout, thus limiting the issue's impact to a smaller number of users. However, please note that you still can't roll the version back for the affected users, so staged rollouts are there to mitigate the impact of potential issues, not to resolve them.
Another challenge is bandwidth consumption on the end users' devices and the overall impact of the app update process. Going back to backend systems for a moment, you can deploy backend apps multiple times a day and the users won't even notice. In contrast, if you ask your mobile users to download app updates too frequently, this might affect them negatively, so they might not be happy about these updates at all.
JavaScript Workaround
The limitations described in the previous section stem from the need to distribute updates to native mobile apps through the app stores. Once you remove this restriction, new possibilities open up.
One of the most common workarounds used in the industry involves executing JavaScript code inside native mobile apps. Since JavaScript can be fetched dynamically (just like standard web-frontend code), you can change its behavior at any time, without going through the full app update process again. This allows you to implement truly dynamic features in your app that can be delivered continuously.
There are even full frameworks written in JavaScript, like React Native, that support special tools to facilitate Continuous Deployment. Though if you use these frameworks, then your app is no longer "native".
That said, please be aware that app stores don't like dynamically fetched JavaScript in apps. They especially dislike it if you use dynamic JavaScript to change app's major features. Therefore, while JavaScript can be used to implement small dynamic features (for example: customizable product promotions), you might get in trouble if you use this "hack" to bypass the app store as a distribution channel. Proceed with caution.
Conclusion
Continuous Deployment is the gold standard of software developments workflows. Unfortunately, while you can (and, in my opinion, should) do Continuous Integration and Delivery with native mobile apps, you'll face major obstacles with Continuous Deployment in mobile. Too bad, but c’est la vie.
Said all the above, even without a full Continuous Deployment, you can still achieve a high degree of automation with mobile apps. This will make your workflows more predictable and spare your team lots of manual effort. Therefore, nothing I said in this article should discourage you from constantly looking for ways to improve your CI/CD setup.
Thank you for reading and, if you're in the search for the best CI/CD platform for mobile applications, please have a look at our offerings.