Skip to content

Best Practices

Here are some best practices to follow when using the Live Update SDK to ensure a smooth user experience:

Automatic Rollbacks

The Live Update SDK supports automatic rollbacks in case an invalid bundle is provided. To enable this feature, you first need to configure the readyTimeout configuration option in your Capacitor project. This option specifies the maximum amount of time to wait for the app to be ready before rolling back to the built-in app bundle.

capacitor.config.ts
import { CapacitorConfig } from "@capacitor/cli";

const config: CapacitorConfig = {
  plugins: {
    LiveUpdate: {
      readyTimeout: 10000
    }
  }
};

export default config;
capacitor.config.json
{
  "plugins": {
    "LiveUpdate": {
      "readyTimeout": 10000
    }
  }
}

We recommend setting the readyTimeout to a value that balances user experience and the need for timely updates. A value of 10,000 milliseconds (10 seconds) is a good starting point. The app now has a maximum of 10 seconds to call the ready() method before the SDK rolls back to the built-in app bundle. You can adjust this value based on your app's specific needs. Larger apps may require a longer timeout.

import { LiveUpdate } from "@capawesome/capacitor-live-update";

const initializeApp = async () => {
  await LiveUpdate.ready(); // Call this method BEFORE any other Live Update methods, e.g.:
  // await LiveUpdate.sync();
};

Make sure to call the ready() method as early as possible in your app's lifecycle to ensure the SDK is properly initialized and ready to handle updates. For example, in Angular, you could call this method directly in the constructor of your AppComponent.

Automatic Storage Cleanup

Since each billing plan includes a fixed quota of storage space, it is important to implement a strategy for automatically cleaning up unused or outdated bundles to avoid exceeding this limit. There are two main approaches to achieve this:

Both approaches can be used either individually or in combination.

Bundle Expiration Dates

The first approach is to set expiration dates for your bundles. This ensures that outdated bundles are automatically removed after a certain period of time. For example, you can use the following Capawesome CLI command to create a bundle that expires after 365 days:

npx @capawesome/cli apps:bundles:create --expires-in-days 365

In most cases, such a long expiration period is enough to ensure that users have ample time to update their apps before the bundles are removed.

Channel Bundle Limits

The second approach is to set limits on the number of bundles that can be stored for each channel. This ensures that older bundles are automatically removed when the limit is reached. For example, you can use the following Capawesome CLI command to create a channel with a bundle limit of 3:

npx @capawesome/cli apps:channels:create --bundle-limit 3

As soon as the limit of 3 bundles is reached, the oldest bundle will be automatically removed to make room for the new one.

Binary Compatible Changes

It is important to make sure that only Binary Compatible Changes are delivered to your users to prevent incompatible updates.

Capawesome Cloud offers two different ways to restrict live updates to specific native versions:

Versioned Bundles

Versioned bundles allow you to restrict live updates to specific native versions by defining a range of version codes for each platform.

Version Code

The version code (named versionCode on Android and CFBundleVersion on iOS) is the internal version number of your app. It is used to determine whether one version is more recent than another and must be incremented each time you release a new version of your app.

To create a versioned bundle, you only need to specify the minimum and maximum version codes for each platform:

  • Minimum Version: The native binary must have at least this version code to be compatible with the bundle.
  • Maximum Version: The native binary must have at most this version code to be compatible with the bundle.

For this, you can use the following Capawesome CLI command:

npx @capawesome/cli apps:bundles:create --android-min 10 --android-max 12 --ios-min 10 --ios-max 12

Versioned Channels

Versioned channels allow you to restrict live updates to specific native versions by creating a channel for each version code. This is the recommended approach, as it leaves less room for mistakes and makes bundles easier to manage. Channels also offer advanced features such as bundle limits.

To create a versioned channel, you can use the following Capawesome CLI command:

npx @capawesome/cli apps:channels:create --name production-10

In this example, we created a channel named production-10 for the version code 10.

To upload a bundle to a specific channel, you can use the following Capawesome CLI command:

npx @capawesome/cli apps:bundles:create --channel production-10

Finally, we just need to set the correct channel in the app to ensure that only compatible bundles are downloaded:

import { LiveUpdate } from '@capawesome/capacitor-live-update';

const sync = async () => {
  // Get the version code of the native app
  const { versionCode } = await LiveUpdate.getVersionCode();
  // Automatically download and set the latest compatible bundle
  await LiveUpdate.sync({ channel: `production-${versionCode}` });
};

Code Signing

We strongly recommend signing your app bundles to ensure their integrity and authenticity. This way, you can be sure that the bundles have not been tampered with and are coming from a trusted source. For more information, check out the Code Signing guide.

Reasonable Update Checks

While it's important to keep your app up-to-date, checking for updates too frequently can lead to a poor user experience. Not only does the device get rate-limited after a certain number of requests, but these requests also use up a lot of the device's resources like battery and data.

You should definitely NOT check for updates in fixed intervals, such as every few seconds:

import { LiveUpdate } from "@capawesome/capacitor-live-update";

// Do NOT do this!!!
setTimeout(() => {
  LiveUpdate.checkForUpdate();
}, 60000);

Instead, we recommend implementing a reasonable update strategy that balances the need for timely updates with the overall user experience. Check out the Always Latest update strategy for an example of how to achieve this.