The Busy Answer: A 503 With SERVICE_BUSY and Retry-After From Our Own API Host
I work on OnePassApps, the team behind app.onepassapps.com. This post is about one answer our own API host gives that nothing we have published has covered yet: the busy answer. Everything here was measured on the night
I work on OnePassApps, the team behind app.onepassapps.com. This post is about one answer our own API host gives that nothing we have published has covered yet: the busy answer.
Everything here was measured on the night of 10 November 2026, UTC, from outside the browser, signed out, over plain HTTPS, with no cookies and no JavaScript.
The answer itself
When api.onepassapps.com is busy, it answers 503, and the body is a JSON envelope with a fixed shape:
{"ok":false,"error":{"code":"SERVICE_BUSY","message":"The service is handling its current workload. Retry shortly.","details":{"retryAfterSeconds":1}},"meta":{"requestId":"req_..."}}
Five things to read out of it. The status code is 503. The error code is SERVICE_BUSY. The message says the service is handling its current workload and asks the caller to retry shortly. The details object carries exactly one number, retryAfterSeconds, set to 1 - and the same response carries a matching Retry-After: 1 header. The meta object still carries the request id, so a busy answer is still traceable to one request. The request id in the copy above is elided because it changes on every response.
How I caught it
I asked seven routes on the API host, one request each. Four of them answered 503 at that moment: /api/products, /api/runtime, /api/membership and /api/vote-board. /api/health answered 200. /api/plans answered 200. /api/public-conversion answered 404.
Then I sent 12 simultaneous requests for /api/products, the catalogue route. Four of them answered 200 with the full 15,650-byte catalogue. Eight answered 503 with the 195-byte busy envelope above.
The counters do not explain it
The API host advertises its own budget in the headers. Every API response I measured carries X-Concurrency-Limit and X-Concurrency-Remaining, and most also carry X-RateLimit-Limit and X-RateLimit-Remaining.
On all eight 503 answers, X-Concurrency-Limit read 64 and X-Concurrency-Remaining read 0. But that counter does not line up with the answer: two of the four 200 answers in that same burst also carried X-Concurrency-Remaining: 0, and the four successful ones read 2, 0, 1 and 0.
The rate-limit pair behaves differently. On the 503 answers the pair was missing entirely - no X-RateLimit-Limit and no X-RateLimit-Remaining - while the 200 answers and the 404 answer in the same sweep carried both.
I could not reproduce it on demand
Later the same night I repeated the sweep: the same seven routes, three rounds each, 21 requests in total, two seconds between rounds. Twelve answered 200, nine answered 404, and not one answered 503. /api/membership and /api/vote-board, which had answered 503 in the first sweep, answered 404 in every round this time.
A second burst of 12 simultaneous requests for /api/products, later again, was answered 200 on all 12 - 15,650 bytes each, with X-Concurrency-Remaining between 57 and 63.
So this post documents an answer I caught, not one I can trigger on purpose. The host shares its capacity with whatever else is running against it, and the numbers above are what my requests saw.
The limits are not the same on every route
Two of the counters differ by route. X-Concurrency-Limit is 64 on /api/products, /api/runtime, /api/plans, /api/membership and /api/vote-board, and 8 on /api/health. X-RateLimit-Limit is 120 on the first group and 60 on /api/health.
The remaining counter only ever went down during the sweep. On /api/health it read 59, then 58, then 57, one step per round. On /api/products it read 119, then 113, then 107. On /api/runtime it read 118, then 112, then 106. On /api/plans it read 117, then 111, then 105. I measured those numbers; I am not claiming what sets the step.
The other three routes answered 404 for the whole sweep, with a 124-byte body - and they still carried the counters, so the counters ride on an error answer too.
The document host never answers this way
All 56 URLs in our sitemap answered 200 in the same sweep, and not one of them carries Retry-After, X-Concurrency-Limit, X-Concurrency-Remaining, X-RateLimit-Limit or X-RateLimit-Remaining. The busy answer, the retry hint and the counters are an API-host thing only.
What I did not measure
One night, one build, one network, one region, no cookies, no JavaScript, no session and no sign-in. I measured what the server sent; I did not open a browser, so nothing here is a statement about what a browser does with a 503. I asked seven API routes out of the ones the host serves, so I make no claim about the ones I did not ask. I did not try to make the host busy on purpose.
The rate-limit numbers on these responses are not new either: an earlier post measured them in more detail - https://dev.to/onepassapps/the-rate-limit-is-not-one-number-120-60-and-30-on-the-same-api-host-and-the-one-route-that-2ech - and this post is about the answer that comes back when the host is busy, not about the limits themselves.
Try it yourself
The home page is where all nine apps are listed, and every one of them runs in your browser tab: the OnePassApps home page
Every app and studio has a plain-language guide with its limits and its tool list: the OnePassApps guides
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.