Last updated Mar 10, 2025

App migration transfers

A migration transfer is a representation of your app's migration. Over the course of the migration, your app primarily interacts with the transfer.

A single transfer, as a monolithic entity, can cover an entire migration. However, complex migrations can benefit from a logical division by using multiple transfers. Having multiple transfers allows you to manage the migration in smaller, more manageable parts. It provides the customer with better visibility, and in case of failures, allow individual logical parts of the migration to be independently retried.

Splitting complex migrations with multiple transfers

If those reasons resonate with your app, you can split your migration into multiple transfers. Each transfer can represent a logical part of the migration. For example, you could have a transfer to handle critical data and another to handle entities that can be remediated outside the migration downtime window.

Transfers can be blocking or non-blocking, indicating which ones (the blocking ones) would prevent the customer from resuming their work. In another words:

  • blocking transfers - should contain critical data from your app that customers cannot function without or data that critical data is dependent on. If we take confluence as an example this could be pages, spaces, users.
  • non-blocking transfers - this is auxiliary data that customers don’t see as part of the core experience for your app. If we take confluence as an example, this could be page analytics, page history.

Transfers can also have dependencies on other transfers, meaning they can't start until the dependent transfers are completed.

You can model those aspects above by implementing the interface MultiTransferDiscoverableForgeListener or MultiTransferDiscoverableListener in your Forge or Connect app, respectively. That will prompt you to implement the method getTransferDefinitions(), and the returned TransferDefinition objects should describe the transfers and dependencies in the most efficient way your app can handle them.

For a complete example of how to use multiple transfers, please refer to this sample app

This feature is available on atlassian-app-cloud-migration-listener version 1.5.8 and later.

Creating the transfers

When app migration starts the platform creates new transfers according to the transfer definitions provided by the app. If the app is being triggered as part of a transfer re-run, only that specific transfer will be re-created.

After the transfer is created, the platform triggers the migration listener on your server app, causing the onStartAppMigration() method to execute. At this point the transfer state is IN_PROGRESS.

Learn how to prepare your server app for migration

The platform also notifies your cloud app that migration has started by sending a listener-triggered event. For Connect apps, this is published via webhook.

Learn how to prepare your cloud app for migration

During the transfer

During the migration, the app migration platform sends app-data-uploaded event to the Forge app for each uploaded app-data. The Forge app should acknowledge this by invoking the messageProcessed function from the @forge/migrations module, using transferId and messageId as parameters. These identifiers, unique to the data transfer operation and the specific event, are included in the incoming event payload.

However, if the messageProcessed function is not invoked for any app-data-uploaded event within a 15 minute window for any reason, such as an exception occurring at the Forge app end during processing, the platform sets the transfer state to TIMED_OUT and automatically settles the transfer.

To handle an unrecoverable error during migration, use the messageFailed function from the @forge/migrations module. This sets the transfer status to FAILED instantly. It's recommended to pair this with addLog to offer customers more context and potential solutions for the error.

Settling the transfer

After the data export is completed, the platform requires an explicit call to completeExport function of the gateway to enable admin users to monitor progress. If the method doesn't get invoked, the platform will assume all the data has been exported after 15 minutes of inactivity (e.g. no additional app data uploads).

At the end of the migration, the app migration platform settles the transfer and sets the transfer state to SUCCESS, FAILED or TIMED_OUT based on the scenario.

Once a transfer is settled, a transfer-settled event is sent to the cloud app. Subsequently any request made using the transferId of a settled transfer will return a 4XX response code. This means you can't access the data related to that transfer anymore.

Canceled transfers

When the admin user (or Atlassian support) cancels a transfer, the platform sets the transfer status to CANCELLATION_REQUESTED and notifies your cloud app by sending a transfer-cancellation-requested event. For Connect apps, this is done via webhook.

If your cloud app doesn't acknowledge the cancellation by settling the transfer within 1 hour, the platform automatically settles the transfer. Once the transfer is settled, the state is set to CANCELED.

Learn more about transfer cancellation

Transfer state diagram

The following diagram illustrates the transfer lifecycle of Connect migrations described in the previous sections:

Diagram that illustrates how the the state of a migration transfer changes over its lifecycle, as described in the previous sections.

Rate this page: