2026 point-based rate limits

Hi @MaheshPopudesi,

I want to raise an interesting “Noisy App Neighbor” edge case that has come up in community discussions.

Currently, we see a path where the activity of one app can inadvertently “noise out” another, causing it to hit rate limits through no fault of its own.

The “Noisy App Neighbor” Scenario

When a high-intensity app (such as a backup or export tool) calls the Confluence API to fetch the export_view of a page, Confluence must render all embedded content. If that page contains macros from other vendors, those apps are hit with a surge of render requests triggered by a single API call they didn’t initiate.

While this inter-app impact exists today, it’s poised to become a much more significant pain point under the new tiering system. If a “Higher Tier” app performs these heavy exports, it could easily exhaust the limits of “Lower Tier” macro providers who are operating on much tighter quotas.

How Point-Based Design Can Bridge the Gap

A point-based system is the ideal mechanism to solve this, provided the “cost” aligns with the actual system strain. Ideally, fetching a page with 50 complex macros should cost significantly more points than fetching a plain-text page.

However, looking at the current proposed scheme, all GET operations for pages seem to be treated with a flat cost. This creates two issues:

  1. Subsidized Impact: The initiating app performs a high-impact operation (triggering dozens of third-party renders) for the same point cost as a simple read.

  2. Disproportionate Risk: The macro-providing apps bear the brunt of the execution load and the resulting rate-limiting risks, which is particularly punishing for apps in lower tiers.

A Path Forward?

To truly mitigate this, has the team considered dynamic costing for page reads? For instance, adding a variable point cost to GET requests based on the complexity of the view (like export_view) or the density of embedded macros. This would ensure the initiating app pays a price proportional to the downstream load it creates, protecting the rest of the ecosystem from this “neighborly” noise.

I’d love to hear your thoughts on whether the point scheme might eventually be refined to account for this type of inter-app impact!

Thanks!

5 Likes

We’ve confirmed the issue. When a user or app makes certain requests, it can trigger the adfExport function for your macro to run for every macro on every page in the results. Because this is an N+1 problem, it causes massive request spikes and is immediately blocked by rate limiting.

e.g. run a request like this for a macro that has an adfExport function

/wiki/rest/api/search
?cql=macro+IN+(“your-macro-key”)
&expand=content.body.export_view

You’ll notice you get hundreds or thousands of invocations if you paginate on those.

At scale, this looks like this:

This means users, other apps or vendors, can unknowingly perform Denial of Service attacks on others apps and wipe out their credits.

Doing the math:

  1. Each search result page requests 25 pages with their full content.
  2. Every page contains 25 macros, each running an adfExport function.
  3. That’s 25 × 25 = 625 function calls per search result page.
  4. Assuming 100 pages of results that is 625 x 100 = 62,500 invocations

At this point, your invocations never happen, but if they did, it would get worse:

  1. If each function makes 3 API calls, that is 625 × 3 = 1,875 requests per result page.
  2. Over 100 search result pages, you’ll get 1,875 × 100 = 187,500 API requests.

All of this happens in the space of 1-2 minutes, so it’s impossible to deal with regardless - I’m also not sure if this happens in other places - e.g. Rovo getting page content, re-indexing etc.

13 Likes

Thanks @JackGraves for providing an example and backing it up with data!

1 Like

@AlanBraun / @ChrisHemphill1 I think it is imperative that Atlassian further postpones the enforcement of the new rate limiting policy.

@AlanBraun, you promised that you would revisit this thread and respond to new topics being raised. Both myself as well as @scott.dudley has done so. In addition, others have also asked questions. None of these have received any response.

Now @JackGraves is bringing you the receipts. The theoretical issues that we already described in full have been proven correct by Atlassian. Even without malicious intent, and by simply using a default feature of Confluence as it was designed, users will unknowingly trigger Appmageddon.

Looking forward to hearing from you

8 Likes

Hey @JackGraves

I want to acknowledge that you’ve raised a legitimate problem here that warrants further investigation.

However, function invocations are governed by a fixed rate limit as documented on https://developer.atlassian.com/platform/forge/limits-invocation/. Function invocations will not be subject to the points-based rate limiting for REST APIs being discussed in this thread.

It sounds like a function invocation being triggered from a CQL search is pretty undesirable behaviour for multiple reasons, not the least of which is the denial of service issue that you’ve raised. Let’s follow up on this problem separately.

3 Likes

@HeyJoe, even though the invocations are not subject to the point-based rate limiting, the logic within the function might trigger requests to the API, as also pointed out by @JackGraves.

Doing the math:

  1. Each search result page requests 25 pages with their full content.
  2. Every page contains 25 macros, each running an adfExport function.
  3. That’s 25 × 25 = 625 function calls per search result page.
  4. Assuming 100 pages of results that is 625 x 100 = 62,500 invocations

We can adjust his math with the 1200 invocations per minute rate limit. Let’s assume that of those 62,500 invocations, 1,200 get executed.

It is highly likely that those 3 API requests, at least 1 is about permissions (2 point). The other 2 are standard GET operations as we are dealing with an ADF export. Which means that each invocation consumes 4 points. 1,200 invocations x 4 points = 4,800 points.

That is ~7.5% of the hourly quota consumed by a single CQL search. And personally I think @JackGraves was being conservative with an average of 3 API requests per invocation.

4 Likes

Thanks, @remie and @JackGraves, for highlighting this concern.

Forge function invocations and REST API rate limits are governed by separate systems. Invocation limits cap how many functions can actually execute in a given window; only those successful executions can go on to make REST API calls and consume points as you noted. That said, you’re right that even a capped number of successful invocations can still generate REST traffic.
The points‑based model is designed with safeguards to tolerate such short‑lived spikes within an hour and to mitigate noisy‑neighbor effects for Tier 1 apps.

1 Like

Would you mind sharing these safeguards? If you’re building a PaaS I guess that making the platform limits public would be the bare minimum.

I see a worrying trend in this conversation: Atlassian’s feedback boils down to “if marketplace apps stop working, that’s ok”, at least that’s what I understand when reading

Invocation limits cap how many functions can actually execute in a given window

If there’s a perfectly legitimate use case – like the one that @JackGraves mentioned – that can cause a trivial and boring app to exceed the platform limits, there’s a problem.

Either marketplace apps are meant to be disposable and customers shouldn’t rely on them – in which case… well, read the room, we’re on CDAC after all – or the new platform limits are inadequate… or at the very least people here are concerned that limits might be inadequate because they weren’t communicated in a way that makes us feel comfortable in our ability to keep delivering the features that our customers pay for.

8 Likes

After nearly 130 posts in this thread, Paolo’s post above says it all.

1 Like

I believe @AlanBraun wrote previously that Atlassian would not be sharing more details on additional limits or the backing models, because security (or something to that effect).

The root cause of most vendor concerns is still Atlassian’s design choice of a one-hour window. This has been brought up a few times, but explaining the necessity of the duration of this window has never been properly addressed in Atlassian’s responses in this thread.

A one-hour window can lead to catastrophic failure of an app, and the imposition of this model creates a new failure mode that did not exist previously. Atlassian is telling vendors: “it’ll be ok, trust us” while also simultaneously saying that it cannot share any details about how this will work. We have only vague, hand-wavy gestures telling us that undisclosed tolerances will fix it, but in the end, it is our customers who will be mad at us (not Atlassian) when they do not, and vendors will take the reputational (and financial) fallout whenever something goes wrong. If Atlassian measured demand incorrectly, or if overall demand changes in the future, then vendors are stuck holding the bag.

If Atlassian told vendors that rate limits reset over a five-minute window rather than a one-hour window (with proportionately lower limits), you would solve 90% of the complaints here. A 2-3 minute outage is not ideal but it is generally tolerable by users. A 30-minute outage is not.

I will say it outright: if the system is designed so that apps can easily and inadvertently exhaust an entire hour’s worth of quota in a few minutes with no recourse for the rest of the hour, then the system is designed incorrectly. At some point or another, this limit will hit multiple vendors due to mistakes or design choices in other parts of Atlassian (such as the ADF macro rendering mentioned above), so I see this as a “when and not if” scenario.

Vendors are also worried because Atlassian teams have a tendency to ship things and then quickly vanish (shift focus, get transferred to another team, etc). Once something is deployed, getting Atlassian to apply changes to existing, already-shipped infrastructure is extraordinarily hard, especially with the near-constant rotation of personnel, and vendors would need to start this conversation all over again to try to beg for a change.

Why can Atlassian not reduce the “accounting boundary” to a substantially shorter time period? Or use a token bucket that is gradually replenished? Or anything else that does not involve potentially locking out apps for an hour and creating crises where none needs to exist?

No one thinks that Atlassian should not have rate limits or should not take steps to protect its infrastructure. I believe Atlassian can still do all of that without forcing hour-long windows.

PS: As of now, this thread has received an aggregate of over 1,100 hearts, which I believe is the most-liked thread ever on CDAC (by a factor of at least 2X). Perhaps that gives some indication of how strongly vendors feel about the issue.

13 Likes

Thank you all for your patience as we review and work through your questions in this thread. Marketplace apps are a critical part of Atlassian’s platform. We want to make platform behavior around points-based rate limits more predictable and transparent for partners and our shared customers.

We have a few updates to share

  1. DC‑to‑Cloud migration exemption

  2. Clarification on Forge UI API usage and points‑based rate limits

DC-to-Cloud migration exemption

App traffic originating from tenants that are actively migrating from Data Center (DC) to Cloud is exempt from points-based app quota rate limits for the duration of the migration window, regardless of the app’s rate-limit tier. Traffic from non-migrating tenants continues to be governed as normal.

Forge UI API usage and points-based rate limits

For the March 2 enforcement, only app‑initiated backend traffic counts toward points‑based rate limits. Direct, user‑initiated UI calls from Forge UI to Jira or Confluence using @forge/bridge.requestJira (with no resolver or backend) is treated as standard UI traffic and is not included in points. By contrast, any Jira or Confluence API calls made by a Forge backend or remote service are included in points‑based rate limit calculations. We may include this category of traffic in points‑based limits in the future, with clear advance notice, but it will not be counted as part of the March 2 enforcement.

Please find more details in the Quick Reference Guide. We will update other documentation sources shortly as well, and we’ll continue to circle back to other questions in this thread.

Does this mean that user-initiated calls from the UI to a backend that calls the API are included?

Hi @markrekveld
Yes, here is what is counted:

  • App‑initiated backend calls
    • for example, UI → resolver → backend (@forge/api)
  • Forge Remote flows invoked from the UI
    • for example, UI → @forge/bridge.invokeRemote() → Forge backend/remote service → Jira/Confluence API
  • Forge Remote flows invoked from backend code
    • for example, UI → @forge/api.invokeRemote() → Forge backend/remote service → Jira/Confluence API

Hi @MaheshPopudesi ,

Thank you for your replies and explanation.

Currently rate limit headers are not available in frontend calls, and now it seems some part of Atlassian wants us to use a resolver instead of using requestJira/requestConfluence.

Please have a look at Jira and Action Required: Update your Apps to comply with Jira Cloud Burst API rate limits - #13 by SuyashKumarTiwari .

Following up this advice would paradoxically make it more likely for us to hit rate limit headers.

Additionally our customers would suffer, because our apps become slower.

4 Likes

Hello all,

We’re rolling out two new Beta rate limit headers on Jira and Confluence REST APIs for points-based quota limits. These headers follow a unified, structured model aligned with rate-limiting header standards. They are informational only; they don’t trigger enforcement or throttling. They are additive, and existing X-RateLimit-* headers are still returned. The rollout will be complete in the next 24-48 hours across all traffic.

Beta-RateLimit Headers Rolling Out on Jira and Confluence REST APIs

  • Beta-RateLimit-Policy - A static header that describes the rate-limit policy applied to the request.

    • Example: Beta-RateLimit-Policy: “global-app-quota”;q=65000;w=3600
  • Beta-RateLimit - A dynamic response header that provides usage signals for applicable rate-limit policies

    • Example: Beta-RateLimit: “global-app-quota”;r=13000;t=600

At enforcement, these headers will drop the Beta- prefix and become RateLimit-Policy and RateLimit. For points-based quota enforcement, only these new headers will be used.

For full details, including header format, parameters, and usage examples:

Thanks for highlighting this @marc. I will review this with our teams.

1 Like

Hey @MaheshPopudesi,

thank you for the additional beta headers. I think that helps us to estimate better if and how we’re encountering rate limits with the new model.

Testing timeframe
AFAIK, the point-based rate limits will be rolled out beginning of March - that’s quite a short timeframe for applying the new headers, gather some traffic, understand how we’re doing with the new point-based rate limits - and possibly improve our code further.
I’d appreciate a longer time.

Understanding Headers
I’ve seen the update in the docs that the two new headers are now also described - and appreciate the detailed description of them.

I’m a bit irritated by this sentence though:

For points-based quota enforcement, only RateLimit and RateLimit-Policy will be used — the existing X-Beta-RateLimit-* and X-RateLimit-* headers will not be used for quota enforcement.

So, what happens when the headers actually go live? What will the existing X-RateLimit-* headers show? Will the RateLimit-Reason header still show e.g. ‘jira-quota-tenant-based’? If these headers are not used for point-based rate limiting, are they still used for burst rate limits or per-issue rate limits?

Most important question
Looking at all the headers is informative and I’d like to understand it better to also better design our apps. The most important question for me would probably be:

Is it safe to assume that all the rate limit mechanisms reliably update the Retry-After header?

We’ve based our current rate limit handling already on that header - and in the end, that’s all that really matters to our app. How long should we wait before we perform another request?

1 Like

Following up on my own response with a suggestion. How about combining all the various rate limit policies now into your new headers?

You could define 5 policies:

  • global-app-quota: A quota applied to your app globally across all tenants (Tier 1)
  • tenant-app-quota: A quota applied per tenant, per app (Tier 2)
  • burst-app-quota: As described in the docs
  • per-issue-short-quota: As described in the docs
  • per-issue-long-quota: As described in the docs

And include all of them into your responses, e.g. like this (if it’s near the limits):

Beta-RateLimit-Policy: "global-app-quota";q=65000;w=3600,"burst-app-quota";q=100;w=2,"per-issue-short-quota";q=20;w=2,"per-issue-long-quota";q=100;w=30
Beta-RateLimit: "global-app-quota";r=11000;t=600,"burst-app-quota";r=50;t=1,"per-issue-short-quota";r=15;t=1,"per-issue-long-quota";r=90;t=20

That would be a transparent way for me as a consumer to understand - and thus better behave as an app.

I appreciate the recent clarifications around DC-to-Cloud migrations, as well as the modification of the scope to exclude front-end requests, and I am glad that Atlassian is willing to shift course based on community feedback.

I wanted to highlight a few more issues:

Issue #1: Points hidden until 80% of quota used

For the new rate limit headers, Atlassian writes that the following is a best practice:

  • Distribute requests over time: Spread your requests evenly throughout the hour, rather than sending large bursts at predictable intervals.

The points-based consumption is hidden until the client hits 80% of quota. How does Atlassian propose that apps implement its suggested best practice without providing this information? Can Atlassian make the “consumed points” visible at all times?

If Atlassian is not going to budge on hour-long windows, apps need to be able to spread their points across the entire hour. Apps cannot do this unless they know how many points they have (and how many they have already spent). This is a critical problem (for example) for batch jobs that might otherwise consume many points all at once; Atlassian is enforcing a cut-off policy that resets only once an hour, so the onus is on the application itself to meter its usage appropriately.

If Atlassian provides near real-time information about points available, apps can do this effectively and implement internal backoffs to meter out points (even if Atlassian is not yet requiring retries itself). In other words, the app gets to decide when it spends its quota.

If this information is hidden until only 20% of quota is remaining, this leads to worse outcomes for everyone: if many points are consumed all at once, suddenly, apps need to make do with 20% of quota for the remainder of the hour (however long that might be), impacting user experience and other tasks. This problem is especially critical for sites in the global pool.

Issue #1b: Can Atlassian return the points cost-per-request in headers?

To help vendors identify expensive operations, could Atlassian please consider providing a header that describes the points consumed by each specific request?

Issue #2: Vendor inability to test rate-limiting

Atlassian is now proposing the use of eight (!) different headers to govern rate-limiting. To say the least, this is a complex implementation. Points-based information is not provided until an app reaches 80% of its quota. Atlassian’s terms of service prohibit vendors from stress-testing Atlassian servers. The only way for vendors to validate their points-based retry logic is in production (!) with real, paying clients.

If Atlassian were to provide points-based consumption with all requests, vendors would at least be able to test some of their rate-limiting logic in the dev environment (for example, by having a development app pretend that its limit is 1000 points and then confirming if it moderates requests appropriately).

While this argument could certainly have been made for the preexisting burst rate-limiting, the new hour-long window comes with severe penalties (loss of access to app for an extended period of time) if the quota is exceeded, which makes the need for testing much more important here (and the implementation is also much more complex).

Issue #2b: Complexity of headers

I agree with @matthias that it would be far better if all of the rate-limiting headers could be combined into a pair of headers that provides all essential information. While the existing headers presumably need to remain for backwards compatibility reasons, it would be ideal to centralize all of this information in one place so that apps have one source of truth.

Issue #3: Timeline

I second @matthias’s comments about the March timeline still being aggressive for implementing the handling of the new headers, across all apps and all vendors. Do not forget that Atlassian’s timeline for imposing Connect financial penalties is also at the end of that month, so most vendors are already quite busy with Forge migrations.

10 Likes

Yes, I agree with your point here, Remie. I think we need to fix the frivolous invocations of the app by the Atlassian product.

3 Likes