Questions about billing for Forge asynchronous invocations

:waving_hand: Hi everyone!

I’ve just published an announcement in the Forge developer changelog that we’ll start charging for usage of asynchronous invocations from 1st July 2026. This follows a decision in December last year to pause billing for this type of compute consumption until there was adequate visibility and advance notice into your usage.

In order to help you review and optimise your future costs, the Forge developer console now provides a breakdown of compute usage, split by sync and async invocations:

If you have questions or concerns about this change - please let me know in this topic.

Hi,

the data in the dev console, is this based on all days of the current month or do we need to wait a couple of days to be able to project monthly costs?

Best regards,
Christopher

Hi @chrschommer,

Great question, for the current month we only have the last ~10-15 days of data flowing. Would be best to wait for the next month to get a fair understanding of the projected month costs.

Hi @HeyJoe , Hi @ChandanaMeka ,

The announcement says:

A Forge app invocation is classified as asynchronous when invoked from the following Forge modules:

Looking at our usage in the developer console, this doesn’t seem right. If I assume that you have data for the last 10 days and interpolate that up to a full month, then our async usage would be ~15% of our overall compute usage.

When I look a the invocations we use and where those are coming from, far more than 90% are invoked by a Trigger module and thus I would expect them to be classified as asynchronous. At least in our case, it doesn’t look like that is the case.

Is this maybe changing with the rollout? Or am I missing something obvious?

Best regards,
Oliver

Hi Team,

Thanks for rolling this out, and I appreciate the breakdown of sync/async compute usage in the “Usages and charges” table.

There are a few places I found the data is either confusing or inconsistent (screenshots are for an internal and unlisted app of ours):

  1. The extra usage breakdown is confusing as the free cap is for total compute. In this case shown below, our sync compute usage doesn’t exceed the free cap, and async usage is waived, so the extra usage is attributed to async only. What happen when sync compute exceed the free cap? What happens when async event is no longer waived - how do you break down the extra usage for sync/async compute? I think an accurate way is to exclude async compute from the total compute (and extra usage) as long as it’s been waived, and no longer show extra usage/charge for async/sync once async is no longer waived.

  2. The Functions details table (../usage/functions) lacks a breakdown dimension for sync/async, which I think would be super helpful for developers to track down usage patterns.

  3. More importantly, in the screenshot below of the Functions details table, you can see the total (68K) is more than sync compute shown above (64K) but much less than the total compute (125K). Because there is no async/sync breakdown in this view, there is no way for me to drill down the data:


    But this chart is unveiling because the app is an internal one where I’m the only user, and because I was out of office from Mar 12-24, I’m pretty sure they would have been no sync compute (UI resolvers) during the period and all usage between Mar 12-24 should be async compute (which is a daily scheduled trigger and usually very consistent workload), which matches the chart. So the chart shown above definitely includes both sync and async compute usage. But if this chart is showing accurate total async+sync usage, then the 125K total shown in the summary table in bullet 1 above must be inaccurate - or vice versa. I cannot reconcile the data in these two views/screenshots.

Thanks,

Shu

Thank you for this feedback, @Shu - our team is looking into this.

Investigating this to confirm why the usage isn’t lining up for you.

What happen when sync compute exceed the free cap?

For forecasting purposes in this UA, we apply the free quota to the sync consumption first, and then apply any remainder to the async compute total. You can see that’s why the waived async compute row show “extra usage” = ~25,747. if the sync compute total exceeds the free cap, then the entirety of the async compute row would be billable.

and no longer show extra usage/charge for async/sync once async is no longer waived.

Yes, once the billing for all types of compute is in effect, the distinction between sync and async is no longer important, and this view will collapse down to a single row again - making the visualisation of the consumption of the free quota much clearer again.

What exactly differentiates async compute from sync compute?

Is async compute counted when:

  1. A Forge module like scheduledTrigger, async events, or queues invokes a function?

OR

  1. Any function execution that happens outside a user request lifecycle?

Basically, the below needs some clarification:

  1. Exactly what events count as async compute

  2. Whether queue pipelines multiply compute usage

  3. How developers should estimate async workloads

  4. Whether background compute should be priced differently

What exactly differentiates async compute from sync compute?

A Forge app invocation is classified as asynchronous when invoked from the following Forge modules:

Whether queue pipelines multiply compute usage

There is no overhead or additional usage charge for asychronous workloads or queueing. In all cases, we just measure the amount of time your code is executing.

How developers should estimate async workloads

We are looking to add some additional details into the usage view that @Shu called out above, which can help provide visibility into async usage. Otherwise, you could instrument your app with additional logs or custom metrics to perform your own measurements.

Whether background compute should be priced differently

no, the charges are the same.

Thank you for the answers. I think that gives a clear perception on how the charges work.

Question 1:
In our case async execution is taking more resources, and it is the hourly scheduled job to check db migrations.
As per code https://developer.atlassian.com/platform/forge/storage-reference/sql-api-schema/
we are using

export const runMigration = async () => {
  try {
    await applyMigrations();
  } catch (error) {
    console.error('Migration failed:', error);
    throw error;
  }
};

export const applyMigrations = async () => {
  const successfulMigrations = await createDBobjects.run();
  console.log('Migrations applied:', successfulMigrations);
};

This approach increases async function execution time, which in turn raises billing costs. Is there a way to reduce or avoid this overhead?

Question 2:
It appears that async scheduled jobs continue to run even if the instance is inactive or the license has expired.

  • Is this correct?
  • If yes, is there a way to stop executing async scheduled tasks for such instances?

@shiv

Note that Atlassian has just release this: https://developer.atlassian.com/changelog/#CHANGE-3260, Skip trigger invocations for installations with inactive licenses.

This should help address the issue in your question 2.