OTA updates in React Native
Tags: javascript, reactnative, ux, mobile
Published: 2024-07-14 14:50:50

Hi there, it's been a long time since I have written a blog on React Native. Today I just want to explain what OTA updates are and how you can use them in your React Native project.

We will deep dive into OTA updates, advantages, and challenges you may face while dealing with this.

### Disclaimer 
This blog covers some advanced topics from my experience building various apps. If you're new to React Native, some parts might be hard to understand, and that's okay. Everyone starts somewhere. Feel free to ask questions or share your thoughts in the comments section.

The idea of this blog is to give you a high-level overview of how OTA updates work in the real world. Instead of covering obvious topics like installation and troubleshooting, I'll focus on helping you understand the real impact of OTA updates when working with a production app.

## What is OTA update? 
OTA stands for Over the Air updates, it's an idea to update your JavaScript bundle on the fly without the need to update the binary (native Android/iOS update). 

![OTA update flow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/04j8zjv0esbe7zux1y6y.png)

Basically, if you have OTA updates configured and you push a new bundle, existing users can download and load the new JS bundle on the next boot-up. 

OTA updates are really helpful to fix UI-related bugs on the fly and sometimes it helps avoid submitting your apps for review which can take up to 7 days. 

> There is also one popular method known as Server Driven UI that lets you control the behavior of the UI from the server. OTAs and Server Driven UI are two separate things. I might write a blog on it in the future but this blog is dedicated to OTA updates. You can share your thoughts in the comment section. 

So now we have understood what OTA updates are in general. Let's understand how it works in React Native. 

In very simple words, OTAs are just for updating your JS bundle on the fly. Roughly speaking, it's just an API call to your server and asking if there has been any update pushed lately or not. The server might give you a JS bundle that you can swap out with the current bundle and load the app, but as you can see things start to get complicated as we speak about swapping the JS bundle and making a server call and loading the JS bundle in the next boot-up. 

To make it easier, there are libraries like [`react-native-codepush`](https://github.com/microsoft/react-native-code-push) and [`eas-updates`](https://docs.expo.dev/eas-update/introduction/) by [Expo](https://docs.expo.dev/) that simplify this process. 

These libraries act as a wrapper around your app and they also provide a CodePush server in which you can configure and push your JS bundle. 

You can refer to their documentation to install this library. If you are facing any issues, you can share them in the comment section.

## Too Easy to break UX

Remember CodePush only updates your JavaScript code. It cannot update your native Java/Objective C code. So it's really easy to break things by accidentally pushing a JS bundle that can break your app if the native modules of that bundle are missing. 

Let's take an example, suppose you have a music app live in the app store and people are loving it. They are using it all day but now you have a product requirement that requires you to access the user's microphone. You decided to install a library that lets you access the microphone. This library also requires you to configure native files such as `MainApplication.java` or `Appdelegate.m`. 

![JS code invokes native function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ku1p8q7scpm4snz3wz3p.png)

You made changes, everything is working locally as expected. You decided to release this update via CodePush. The moment you release the OTA update the app will crash because your JS code is trying to call a native module which is missing. Users have to reinstall the application and you have to immediately revert that bundle so other users won't experience these crashes.

![Picture shows explosion](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m039aofaissz165m2noc.gif)

We had the exact same situation while building Nintee Application. We had to revert the JS bundle and ask users to reinstall the app. It's easy to spoil the UX. 

Another challenging part is OTA updates don't reflect immediately.  First, the user needs to download the bundle in the background and load it which can happen in the next app boot. 

So if users install this app, chances are they can load the stale JS bundle which is locally present. UX can easily get out of sync.


## Ground rules

You have to establish some ground rules when you are working with OTA updates. 

Stick to the app version: I made a habit to increment the app version whenever I modified any native code. You can easily differentiate and upload the JS bundle corresponding to the app version. 

![OTA updates for different versions of your app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fb403pxus1amuozpkyqx.png)

For example, 
if Segment A is using version `1.5.2` you can push OTA updates specifically for this segment. This way you can make sure that OTA updates support that App binary and it won't break the app. 

Decide whether you want updates to be visible immediately. Prioritize between OTA and Native binary release. You can also ship both updates at the same time. 

This makes sure if new users are onboarding, they will see the new changes meanwhile existing users can either load JS on the fly or update the binary.  

## What's my take on OTA updates?

These are the technical decisions to make sure the user's UX stays consistent. 

It depends on your team, and the size of your user base to decide whether you should configure OTA in your app or not.

While working at Nintee, we realized that almost 75% of our users don't bother to update the app. They would likely use the old version of the app if there are no major updates. We had a situation where we had to ask users to update the app. This process became cumbersome as we were onboarding more and more users. 

OTA updates help us to push bug fixes, UI improvements, and functionalities on the fly. It was almost like how we update our web applications. 

Since the app distribution platform like Play Store and App Store can take up to 24 hours (sometimes) when an app only contains some bug fixes and minor changes, it is a really frustrating experience for a developer.

You just have to be more careful while working with OTA updates as we saw it's too easy to spoil the User Experience.  

I hope this blog helped you to understand the high-level overview of how OTA updates work at the production level. 

Thank you for reading this blog and I shall come with another exciting blog. Please share your thoughts in the comment section. 

Curious to know more? Check out reference links 

[React Native Code Push library](https://github.com/microsoft/react-native-code-push)  
[Expo eas updates](https://docs.expo.dev/eas-update/introduction/)  
[Manage runtime version with eas updates](https://docs.expo.dev/eas-update/runtime-versions/)  
[Microsoft App Center retiring](https://github.com/microsoft/react-native-code-push/issues/2675)  

Happy Hacking...