2026 point-based rate limits

I hope the Atlassian team recognizes that the point accrual for the get permissions API is broken and fixes it ASAP. If an app can only check permissions 30 times in an hour (and less for larger customers with more users) that is a full blocker. Especially when the Atlassian security profile requires permissions to be re-checked for any backend processing.

Chris

6 Likes

More disturbing behavior observed. See below logs and inline comments

# Normal response with expected behavior
2026-03-26 16:24:52.503 DEBUG org.apache.http.headers - http-outgoing-65 << Beta-Ratelimit-Policy: "tenant-app-quota";q=100100;w=3600
2026-03-26 16:24:52.503 DEBUG org.apache.http.headers - http-outgoing-65 << Beta-Ratelimit: "tenant-app-quota";r=17842;t=2107
2026-03-26 16:24:52.503 DEBUG org.apache.http.headers - http-outgoing-65 << X-Beta-Ratelimit-Reason: jira-quota-tenant-based
2026-03-26 16:24:52.503 DEBUG org.apache.http.headers - http-outgoing-65 << X-Beta-Ratelimit-Nearlimit: true
2026-03-26 16:24:52.503 DEBUG org.apache.http.headers - http-outgoing-65 << X-Ratelimit-Limit: 350
2026-03-26 16:24:52.503 DEBUG org.apache.http.headers - http-outgoing-65 << X-Ratelimit-Remaining: 349


# Quota now reached (r=0)
# issue #1 no more Ratelimit-Policy header received to know total quota and window attributes
# issue #2 the t in Ratelimit is completely off it should be 20XX instead of 27XX
2026-03-26 16:25:28.490 DEBUG org.apache.http.headers - http-outgoing-66 << Beta-Ratelimit: "tenant-app-quota";r=0;t=2788
2026-03-26 16:25:28.490 DEBUG org.apache.http.headers - http-outgoing-66 << X-Beta-Ratelimit-Reason: jira-quota-tenant-based
2026-03-26 16:25:28.490 DEBUG org.apache.http.headers - http-outgoing-66 << X-Beta-Ratelimit-Reset: 2026-03-26T16:00Z
2026-03-26 16:25:28.490 DEBUG org.apache.http.headers - http-outgoing-66 << X-Ratelimit-Limit: 400
2026-03-26 16:25:28.490 DEBUG org.apache.http.headers - http-outgoing-66 << X-Ratelimit-Remaining: 399


#Quota still reached, t still bogus
2026-03-26 16:25:29.914 DEBUG org.apache.http.headers - http-outgoing-67 << Beta-Ratelimit: "tenant-app-quota";r=0;t=2352
2026-03-26 16:25:29.914 DEBUG org.apache.http.headers - http-outgoing-67 << X-Beta-Ratelimit-Reason: jira-quota-tenant-based
2026-03-26 16:25:29.914 DEBUG org.apache.http.headers - http-outgoing-67 << X-Beta-Ratelimit-Reset: 2026-03-26T16:00Z
2026-03-26 16:25:29.914 DEBUG org.apache.http.headers - http-outgoing-67 << X-Ratelimit-Limit: 200
2026-03-26 16:25:29.914 DEBUG org.apache.http.headers - http-outgoing-67 << X-Ratelimit-Remaining: 199


#Quota still reached, t still bogus
2026-03-26 16:25:30.149 DEBUG org.apache.http.headers - http-outgoing-68 << Beta-Ratelimit: "tenant-app-quota";r=0;t=2521
2026-03-26 16:25:30.149 DEBUG org.apache.http.headers - http-outgoing-68 << X-Beta-Ratelimit-Reason: jira-quota-tenant-based
2026-03-26 16:25:30.149 DEBUG org.apache.http.headers - http-outgoing-68 << X-Beta-Ratelimit-Reset: 2026-03-26T16:00Z
2026-03-26 16:25:30.149 DEBUG org.apache.http.headers - http-outgoing-68 << X-Ratelimit-Limit: 350
2026-03-26 16:25:30.149 DEBUG org.apache.http.headers - http-outgoing-68 << X-Ratelimit-Remaining: 349


#Another quota usage, reporting the right t (32*60 = 1920 + 47)
2026-03-26 16:27:12.396 DEBUG org.apache.http.headers - http-outgoing-69 << Beta-Ratelimit-Policy: "global-app-quota";q=65000;w=3600
2026-03-26 16:27:12.396 DEBUG org.apache.http.headers - http-outgoing-69 << Beta-Ratelimit: "global-app-quota";t=1967
2026-03-26 16:27:12.396 DEBUG org.apache.http.headers - http-outgoing-69 << X-Ratelimit-Limit: 350
2026-03-26 16:27:12.396 DEBUG org.apache.http.headers - http-outgoing-69 << X-Ratelimit-Remaining: 349


#Quota reached used again, eventually t is a bit closer to the right value but still off
2026-03-26 16:52:50.620 DEBUG org.apache.http.headers - http-outgoing-72 << Beta-Ratelimit: "tenant-app-quota";r=0;t=510
2026-03-26 16:52:50.620 DEBUG org.apache.http.headers - http-outgoing-72 << X-Beta-Ratelimit-Reason: jira-quota-tenant-based
2026-03-26 16:52:50.620 DEBUG org.apache.http.headers - http-outgoing-72 << X-Beta-Ratelimit-Reset: 2026-03-26T16:00Z
2026-03-26 16:52:50.620 DEBUG org.apache.http.headers - http-outgoing-72 << X-Ratelimit-Limit: 400

I’m going to focus on these two issues observed when the quota is reached

# issue #1 no more Ratelimit-Policy header received to know total quota and window attributes
# issue #2 the t in Ratelimit is completely off it should be 20XX instead of 27XX

I could see #1 being an expected behavior just not documented, however the #2 must clearly be a bug

1 Like

Hi everyone,
I was trying to implement backoff strategy for Forge SQL 429 rate limit errors but I could not find any Retry-After header in the response:

function SQL Error Details: [“{"message": "Limits for the current installation have been exceeded","name": "ForgeSQLError","responseDetails": {"status": 429,"statusText": "Too Many Requests","traceId": null},"code": "RATE_LIMIT_EXCEEDED","context": {}}”]

In Atlassian documentation, it is mentionned that Retry-After headers are going to be returned with responses which would be rate limited at enforcement. Since I do not see them in the Forge SQL response - does that mean that Retry-After header is implemented only on the standard REST API endpoints? If that is the case - how are we suppose to handle rate limits using Retry-After in Async API?

5 Likes

We are starting to see undocumented rate limit reasons in our log, which is quite unfortunate, since we cannot possibly observe our log files for undocumented, new rate-limits each day. Could you please update the documentation to include all possible rate-limits that are now in effect? We were promised this would have no effect on most apps, but now they start popping up left and right without any changes to our usage patterns.

jira-max-concurrent-threads-across-all-instances-per-tenant-per-user

8 Likes

Hi @BurakAKTEPE

We confirmed that Forge front-end traffic is exempted. Could you please re-run the same test when you get a chance? We want to make sure that it is resolved for you as well. If you are still seeing the same behavior, please open an ECOHELP ticket, and we will debug this with you.

I just saw that one of the Jira API returned jira-cost-based as the rate limit reason. Just one example of undocumented reason.

Also I get some inconsistant structure of the response:

"rawHeaders":{
  "Beta-RateLimit":"\"global-app-quota\";r=0;t=3141",
  "Beta-Retry-After":"3141",
  "X-RateLimit-Limit":"600000",
  "X-RateLimit-Remaining":"0",
  "X-RateLimit-Reset":"2026-04-09T13:15Z",
  "RateLimit-Reason":"jira-cost-based",
  "Retry-After":"89",
},

Problems:

  • I get both Beta prefixed and not prefixed headers so how to know if this is enforced or not?
  • r=0 and X-RateLimit-Reset with a value that is just 1.5minutes after. If it is true that this is a global-app-quota - how can it be reset just 1.5minutes after?
  • 2 different retry-after headers in the response (one in beta and one enforced)
  • And undocumented RateLimit-Reason (jira-cost-based).
4 Likes

Atlassian: “new global pool limit for rate limiting”

Also Atlassian:

1 Like