Action Required: Update your Apps to comply with Jira Cloud Burst API rate limits

Hi Hannes,

Thanks for your patience. Here is the response from Atlassian engg team, I have also updated the ticket with this information.

Recommended solution for Forge apps (use backend resolver, not frontend headers)

For Forge apps implementing rate‑limit awareness, the supported and reliable way to read rate‑limit headers today is via a backend resolver using @forge/api, not directly from frontend requestJira calls.

This aligns with Forge’s documented execution model:

  • @forge/api runs on Atlassian infrastructure in the Forge function runtime, with full access to the HTTP Response (including headers) and no browser CORS restrictions.

  • @forge/bridge.requestJira() runs in the browser (Custom UI iframe) and is therefore subject to CORS and Access-Control-Expose-Headers behaviour, as described earlier on this page and in the “Forge FrontEnd Rate Limiting Headers Requirements” doc.

A backend resolver can reliably read the rate‑limit headers and return only the data the UI needs:

// Forge function (backend) – canonical place to read rate-limit headers
import api, { route } from '@forge/api';
import Resolver from '@forge/resolver';
const resolver = new Resolver();
resolver.define('getIssueWithRateLimitInfo', async () => {
const response = await api.asApp().requestJira(
route`/rest/api/3/issue/KAN-1`
);
const rateLimitInfo = {
limit: response.headers.get('X-RateLimit-Limit'),
remaining: response.headers.get('X-RateLimit-Remaining'),
reset: response.headers.get('X-RateLimit-Reset'),
retryAfter: response.headers.get('Retry-After') ??
response.headers.get('Beta-Retry-After'),
};
const body = await response.json();
return { body, rateLimitInfo };
});

The Custom UI frontend then calls this resolver via @forge/bridge.invoke and does not need to read or interpret raw HTTP headers itself.

Why rate‑limit handling should not live in the frontend

Even once Access-Control-Expose-Headers is correctly configured on Jira/Confluence

  1. Browser/CORS limitations remain a moving part
    Frontend access to headers always depends on CORS configuration and browser behaviour. Backend @forge/api calls are not constrained by this, so rate‑limit logic there is more robust.

  2. Security and platform alignment
    Forge documentation and internal guidance consistently model heavy integration logic and product REST API calls as backend responsibilities implemented with @forge/api, with Custom UI frontends calling backend resolvers via @forge/bridge.invoke. This pattern also appears in the public Forge app REST APIs (Preview) documentation, where app logic (including product API calls) is implemented in Forge functions and exposed via apiRoute, and clients—whether UIs or external systems—call those backend endpoints rather than interacting with product REST APIs directly.

Let me know if this explanation sounds reasonable. Feel free to reach out for any doubts.