RFCs are a way for Atlassian to share what we’re working on with our valued developer community.
It’s a document for building shared understanding of a topic. It expresses a technical solution, but can also communicate how it should be built or even document standards. The most important aspect of an RFC is that a written specification facilitates feedback and drives consensus. It is not a tool for approving or committing to ideas, but more so a collaborative practice to shape an idea and to find serious flaws early.
Please respect our community guidelines: keep it welcoming and safe by commenting on the idea not the people (especially the author); keep it tidy by keeping on topic; empower the community by keeping comments constructive. Thanks!
Project Summary
Atlassian is exploring an improvement to Forge app migration progress reporting that would give apps the option of reporting progress more accurately without facing timeouts. The proposal would let apps declare custom migration event types, including estimated totals and weights, then update completed counts during long-running or multi-phase imports. This would help avoid legitimate migrations being treated as stalled, improve customer visibility into progress, and reduce partner workarounds, while preserving the current behaviour for apps that do not need the new APIs.
- Publish: 17 September 2026
- Discuss: Until 01 October 2026
- Resolve: By 15 October 2026
Problem
With Data Center to Connect migrations, Atlassian required App Partners’ cloud apps to send updates that included the percentage completion of a given migration. When completion reaches 100%, the migration is complete. This model worked well for some apps, while others found it difficult to calculate progress, and the inconsistency of progress calculation across the app migration landscape resulted in customer confusion.
The Forge migration model calculates progress from migration events and acknowledgements, not from a partner-reported percentage:
- The server app uploads app data, creating events such as
avi:ecosystem.migration:uploaded:app_data. - The Forge app processes each event and calls
messageProcessed(transferId, messageId)when the import succeeds, ormessageFailed(transferId, messageId)if it fails. - Customer-facing progress advances as uploaded app data events are acknowledged as processed.
- The documented 15-minute inactivity timeout is reset when new app data is uploaded or an app data message is acknowledged.
- If neither happens within that window, the transfer is treated as stalled and fails.
In short, Forge progress reflects observed migration activity rather than an arbitrary completion percentage reported by the app.
However, we’ve observed and heard that the Forge model also does not work well for some apps, leading to workarounds that have required significant effort from app partners. These include, but are not limited to:
- Sending a large number of dummy app data events that are used just in case part of the import takes longer.
- Carefully ordering and scheduling event processing so fast parts of an import are interspersed with slower parts that take more than 15 minutes.
We’ve heard this is a particular problem for apps that need to do post-processing using Jira or Confluence APIs, or that have a multi-phase import process.
Returning to the Connect solution is not a realistic option. Some reasons include:
- Apps have already implemented the Forge solution, and this could break backwards compatibility. We are ideally seeking a solution that adds to what we have now.
- Atlassian systems are now an opinionated contributor to Forge app migration progress calculations. Calculation of progress needs to factor in both Atlassian and app progress.
- For some apps, the Connect solution resulted in a confusing customer experience. For many simpler apps, the current approach requires no special thought and works well for them.
Any solution must not compromise migration reliability; Atlassian has seen examples of customers dropping apps when moving to Cloud because migrating is deemed to not be worth it. To mitigate this, we need a solution that:
- Avoids causing migrations to fail when they are genuinely still in progress.
- Does not slow down migrations significantly.
- Provides customers with good observability into how their app migration is going.
- Is easy for app partners to implement properly.
Proposed Solution
Overview
Our current approach calculates progress as (effectively):

If we choose to address this, we’d instead implement something like:

There would be n different types of events, with i=0 representing the existing Atlassian-tracked events (with weight 1), and zero or more custom event types with weights, total count, and completion counts optionally supplied by the app (defaulting to there being no custom event types). If apps do nothing, the current behaviour would be retained (i.e. this would be an optional improvement for apps that would benefit from it).
Declaring custom event types
At the start of the import, apps would have the option of making an API call with a description for each type of event (which in the future we could show to the customer to provide more detail about progress), and the weight and initial estimate of the eventsTotalCount for that event type. The weights and descriptions would be locked in for the migration.
POST /app/migration/forge/v1/customeventtypes/declare HTTP/1.1
Authorization: Bearer yourToken
Content-Type: application/json
{
"transferId": "d37c7caa-ff0d-4e46-b815-2edc4dc3384c",
"eventTypes": {
"my-custom-event-type-1": {
"description": "Type 1s processed",
"totalCount": 50,
"weight": 3.0
},
"my-post-processing": {
"description": "Jira issues updated",
"totalCount": 3000,
"weight": 0.1
}
}
}
HTTP/1.1 201 Created
Content-Type: application/json
{"status": "success"}
- Apps may choose their preferred set of event types for a transfer.
- Event types can only be declared once per transfer.
- Any event type that is not declared cannot be updated later.
- The declare operation is idempotent, but it cannot be called again with different values for the same transfer.
Updating custom event type statuses
Apps that have made such a call would be free, from time to time, to make another API call (rate-limited to 5 per transfer per 5-minute period):
- Increasing the eventsCompleted values for the custom events. These would be locked to only increasing. Increasing an eventsCompleted value would reset the migration timeouts. If there is no increase, it would be processed idempotently, but would not reset the timeout again.
- Updating the eventsTotalCount to a newer estimate. This could increase or decrease, but not below the eventsCompleted value for that event type.
POST /app/migration/forge/v1/customeventtypes/update HTTP/1.1
Authorization: Bearer yourToken
Content-Type: application/json
{
"transferId": "d37c7caa-ff0d-4e46-b815-2edc4dc3384c",
"eventTypes": {
"my-custom-event-type-1": {
"completed": 10
},
"my-post-processing": {
"totalCount": 2000
},
"invalid": {
"totalCount": 1
}
}
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"my-custom-event-type-1": {
"status": "success"
},
"my-post-processing": {
"status": "error",
"message": "New totalCount less than current completedCount"
},
"invalid": {
"status": "error",
"message": "Event type not registered"
}
}
completedandtotalCountare individually optional. It is valid to provide both in one update, or just one, but at least one must be provided per event type.- If one of the values is invalid, the others will still be updated, with partial errors returned on a
200response.
When eventsCompleted becomes equal to eventsTotalCount for every custom event type, and all existing Atlassian-tracked events are also completed (including by acknowledging app data files and any Simplified App Migration event files), the transfer would be settled as SUCCESS.
Note: This does not provide a way to mark a custom event as FAILED - if this is a possibility, apps should still reserve one app data file to mark as FAILED when they are ready to fail the entire transfer.
Alternative we’re considering - tweaking timeouts
An alternative that we have considered is continuing to adjust the timeouts to a larger value. However, there is no timeout threshold that guarantees an app data file will always finish processing while remaining short enough to prevent customers from assuming a transfer has stalled.
Future extensions
Part of the reason for proposing a short description for each event type is so, in the future, we’ll be able to surface custom event status directly to customers (instead of just a percentage). This will provide additional transparency to customers (meaning descriptions must be clear as customer-facing strings, and the reported counts should be intuitive).
Asks
Atlassian has not yet decided whether we should implement this. A major deciding factor is how many apps would likely adopt the new APIs if we were to offer them.
We’d love to know:
- If we were to implement this solution as is, would you find it helpful for any of your apps? If so, how quickly would you be likely to adopt it?
- Is there anything we could change about the proposed solution that would make it more suitable for your apps?
- If we implemented this, would you be better placed to guarantee some reported forward progress every 15 minutes, or would a longer timeout be necessary? If longer, what maximum interval would you suggest between updates so that your app could reliably report forward progress (assuming it is not genuinely stalled or failing)?
- Is there an alternative timeout interval that would work for you with app data even if we didn’t make this change?