Developer
News and Updates
Get Support
Sign in
Get Support
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Last updated Nov 4, 2026

Prepare your cloud app for Forge container services migration

This page explains how to prepare your cloud app for migration by processing events.

Forge container services is in Preview. Migration support for Forge container services follows the same status.

Events

The Forge container service, endpoint, and trigger modules that you implement will allow the app migration platform to send information about specific migration events that take place on your server app.

Add Forge container service and trigger to the manifest

Define a service, an endpoint, and a trigger to process migration events.

See an example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
modules:
  trigger:
    - key: migration-trigger
      endpoint: migration-event
      events:
        - avi:ecosystem.migration:triggered:listener
        - avi:ecosystem.migration:uploaded:app_data
        ...

  endpoint:
    - key: migration-event
      service: migration-service
      route:
        path: /migration-events

services:
  - key: migration-service
    containers:
      - key: migration-container
        tag: ${TAG}
        resources:
          cpu: "1"
          memory: "2Gi"
        health:
          type: http
          route:
            path: /health

The app migration platform sends each event to your container service as an HTTP POST request to the endpoint route.path.

Refer to the event types for all the events that you can listen for and their associated payloads.

Processing events

If your container service returns an invalid response the migration event will be sent again with exponential backoff up to four times for a total of five attempts.

When processing events it is important to keep in mind the following:

  • Event acknowledgement - you must call status API for avi:ecosystem.migration:uploaded:app_data events within 15 minutes of processing the last event or uploading new data from the server app (whichever occurs later).
  • Events are not ordered - the platform may send events in a different order e.g. avi:ecosystem.migration:uploaded:app_data may appear before avi:ecosystem.migration:triggered:listener.
  • Validate the event payloads and return an error response if validation fails - this will help you monitor for failed invocations and failed invocations will be retried.
  • Containers can be terminated and replaced at any time. Do not rely on in-memory state to track which events you have processed, and only acknowledge an event once its data has been processed.

If you are migrating from Connect and are finding it difficult to ensure you acknowledge an event or upload new data every 15 minutes without a major rewrite of your migration logic, please contact Ecosystem Support; we have some additional temporary options available (subject to approval and periodic review of your use case by Atlassian) to support migrations until you are able to progressively import and acknowledge data.

Event types

You can add the following events to your Forge trigger.

EventDescription
avi:ecosystem.migration:triggered:listenerYour server app migration listener has been triggered.
avi:ecosystem.migration:uploaded:app_dataYour server app uploaded app data.
avi:ecosystem.migration:requested:transfer_cancellationThe user has cancelled a transfer.
avi:ecosystem.migration:errored:listenerAn unhandled exception occurred in your server app migration listener.
avi:ecosystem.migration:completed:export_phasecompleteExport() has been called in your server app to signal to your Forge app that all app data has been uploaded.
avi:ecosystem.migration:settled:transferThe app migration platform has settled the transfer.
avi:ecosystem.migration:uploaded:key_value_pairYour server app uploaded key value pair data.
avi:ecosystem.migration:uploaded:sql_dataYour server app uploaded SQL data data.
avi:ecosystem.migration:preloaded:app_dataYour server app has preloaded data.

Payload

This is the data that is sent in the body of the request to your container service endpoint.

AttributeTypeDescription
eventTypestringThe migration event type.
transferIdstringAn ID (UUID) that the app migration platform uniquely generates per migration.
migrationDetails.migrationIdstringAn ID (UUID) that the app migration platform uses to uniquely identify a migration.
migrationDetails.migrationScopeIdstringAn ID that the app migration platform generates to uniquely determine a source (server) and destination (cloud-site) of migration.
migrationDetails.createdAtnumberTimestamp of when the app migration was created.
migrationDetails.cloudUrlstringURL of the destination cloud site for the migration.
migrationDetails.namestringThe name of the migration plan provided by the user who initiated the migration.
migrationDetails.testMigrationboolean | undefinedWhether the migration is a test migration. This optional field may be present on Forge migration events.
serverAppVersionstring | undefinedThe version of the server app. This optional field is present on avi:ecosystem.migration:triggered:listener events.
keystringAn ID (UUID) to uniquely identify the data your server app uploads to cloud storage. This will only be present on avi:ecosystem.migration:uploaded:app_data events.
labelstring | undefinedMetadata that provides additional information about the data your server app uploads to cloud storage. This will only be present on avi:ecosystem.migration:uploaded:app_data events.
messageIdstringAn ID (UUID) that the app migration platform generates to uniquely recognise an event.
transferError.exceptionTypestring | undefinedMetadata that provides details of the exception type that occurs when executing server side listener method (onStartAppMigration).
This will only be present on avi:ecosystem.migration:errored:listener events.
transferError.safeStackTracestring | undefinedMetadata that provides the stack trace of error that occurs when executing server side listener method (onStartAppMigration).
This will only be present on avi:ecosystem.migration:errored:listener events.

Example payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
  "eventType": "avi:ecosystem.migration:uploaded:app_data",
  "transferId": "3f3a47f2-a6a2-4204-84bb-d0fc504c9dc6",
  "migrationDetails": {
    "migrationId": "403c4f71-a0d1-4a63-97a8-487d18691c46",
    "migrationScopeId": "0ba07dd9-3804-4600-9102-fa6e1efeab08",
    "createdAt": 1723111376499,
    "cloudUrl": "https://your-customer-cloud-site.atlassian.net",
    "name": "Migration Plan Name",
    "testMigration": false
  },
  "key": "e094ca53-3747-4541-b263-0bf7b56a5bca",
  "label": "file-label-you-used",
  "serverAppVersion": "1.0",
  "messageId": "53f88ea7-a2d2-4dd2-9f36-2d8c43401b11"
}

Forge migration REST API

Refer to the REST API documentation for the available endpoints and their usage.

Your container service does not call https://api.atlassian.com directly. Send requests to the egress sidecar using the URL in the FORGE_EGRESS_PROXY_URL environment variable. Prefix the API paths in the REST API documentation with /atlassian, for example /atlassian/app/migration/forge/v1/message/{transferId}/status.

Authentication

Requests to the egress sidecar must contain a forge-proxy-authorization header. Use as=app for all app migration platform requests. There are two ways to identify the context of the request:

OptionHeaderWhen to use
Invocation IDforge-proxy-authorization: Forge as=app,id=<x-forge-invocation-id>While you are handling the request that delivered the event. Use the x-forge-invocation-id header from the inbound request.
Installation IDforge-proxy-authorization: Forge as=app,installationId=<installationId>When you process data after the event request has completed, for example in a background job or a queue worker. Retrieve the ID using the Get app installations endpoint.

For more detail, refer to Forge Container services API contract and Call a containerised service without an invocation ID.

The Forge Container services sidecar authenticates inbound requests to your service, so you do not need to verify the requests yourself.

Example

The following example handles every event sent to the endpoint, and acknowledges only avi:ecosystem.migration:uploaded:app_data events after processing them. It is an excerpt, and uses Node.js with Express.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import express from "express";

const app = express();
app.use(express.json());

app.post("/migration-events", async (req, res) => {
  const event = req.body;
  const invocationId = req.header("x-forge-invocation-id");

  // Validate the payload and process the event
  if (!event.transferId || !event.messageId) {
    return res.status(400).json({ error: "Invalid migration event" });
  }

  // Only uploaded app data needs to be acknowledged. Return 200 for all other event types.
  if (event.eventType !== "avi:ecosystem.migration:uploaded:app_data") {
    return res.json({ message: `Ignored ${event.eventType}` });
  }

  // ... download and import the data identified by event.key ...

  const response = await fetch(
    `${process.env.FORGE_EGRESS_PROXY_URL}/atlassian/app/migration/forge/v1/message/${event.transferId}/status`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "forge-proxy-authorization": `Forge as=app,id=${invocationId}`,
      },
      body: JSON.stringify({ status: "SUCCESS", messageIds: [event.messageId] }),
    }
  );

  if (!response.ok) {
    // A non-2xx response will cause the event to be sent again
    return res.status(502).json({ error: `Status update failed: ${response.status}` });
  }
  return res.json({ message: `Successfully processed ${event.messageId}` });
});

app.listen(process.env.SERVER_PORT);

Error handling

It is important for building reliable migration paths to retry on 5xx and 429 errors for all API calls with exponential backoff and jitter.

Rate this page: