The concurrency budget
The constraint on an Acumatica instance is not a rate limit in the usual sense. There is no "requests per minute" quota to stay under. What is capped is how many API requests can run at the same time, and that cap is a property of the customer's licence tier — an L-series tier allows six.
Six. Not six hundred.
What happens at the ceiling
Requests past the limit are queued, not refused. Once twenty are queued the next one is declined outright, and anything that has waited in the queue for more than a minute is also declined. A declined request comes back as 429.
So a 429 here does not mean "you are going too fast." It means "this instance is at the number of simultaneous API requests it is licensed for" — and the other requests holding those slots may well be the customer's own e-commerce sync or EDI feed, not yours. Backing off is the correct response, and it is done for you with an exponential delay that honours Retry-After.
Why the session is the unit, not the request
Two separate mechanics can consume the budget without you making a single extra query:
A cookie session that is never logged out keeps its slot. Log in, do the work, crash before logging out, and that slot is held until the server times it out on its own schedule. Do that a few times and a six-slot tier is gone. The client always logs out on disconnect, and every widget render disconnects in a finally.
A bearer token alone does not identify a session. This is the surprising one. If you authenticate with OAuth and send only the Authorization header, Acumatica treats each call as a new user and each one takes its own slot. The session cookie returned alongside the token is what says "same user, same session" — so cookies are captured from every response and replayed under both auth modes.
Practical consequences
- The client caps its own in-flight requests below the tier (four by default). Raise
max_concurrenton the account only once you know the tier. - Prefer one query returning fifty rows over fifty queries returning one.
$expandis not free: each expanded collection is more work per row. Expand when fetching one document, not when scanning a page of them.- A scene of eight tiles is eight renders. That is the realistic way to exhaust a tier by accident, which is why every tile shares the discipline above rather than opening its own long-lived session.
- Schema discovery is memoised per client, because probing versions costs up to nine requests and doing that once per parallel tool call would spend the entire budget learning something that does not change.