Topic 31

5xx and Timeouts: The Problem Is on Theirs

Errors

Sunday, 03:07. Vera has scheduled an early run of the Thursday report's data pull, and it comes back with 503 Service Unavailable. For once there is nothing to fix, because there is nothing wrong: Tandem's maintenance window runs from 03:00 to 03:20 every Sunday, the documentation says so, and the response says so too. The request was perfect. The other side was simply closed.

The 5xx family and its cousin the timeout are the weather of APIs. They are not your fault, they are partly forecastable, and they are survivable if you behave well while they last. The whole skill on this page is learning to recognize weather rather than mistaking it for something you did — and then waiting in a way that helps.

What to do when the answer is a 5xx or no answer at all
The response carries Retry-AfterWait exactly that long, then try once
No such header, but the status page says soWait out the posted window
Nothing posted anywhereSpace your retries, each wait longer
It outlasts the posted windowEscalate with time, status, request id

The 5xx Regulars

Four numbers cover nearly everything you will meet. A 500 means the server hit its own bug while handling a perfectly good request — something broke inside, and the message is often deliberately vague because the details are the provider's business, not a caller's.

A 502 and a 504 both point at a middleman. Requests rarely travel straight from your machine to the program that answers them; there is usually something in between that receives the request and passes it along. When that go-between cannot get a usable answer out of the program behind it — no answer at all, or a broken one — you get 502; when it is still waiting and finally gives up, you get 504. You do not have to know what the middleman is called to read the signal: something in their chain did not respond.

A 503 means the service is deliberately not answering right now — overloaded, or in maintenance. This is the friendliest of the four, because it often arrives with a header called Retry-After, which is the server scheduling your patience for you. Vera's Sunday response carries one.

The honest 503 — a closed sign with the reopening time on it
HTTP/1.1 503 Service Unavailable
Retry-After: 780
Content-Type: application/json

{"error": {"code": "maintenance",
           "message": "Scheduled maintenance, back at 03:20",
           "request_id": "req_9f2c"}}

Read it the way Topic 29 taught. The status says the problem is on their side. The message names the reason and the reopening time. And the header holds a number of seconds — seven hundred and eighty of them, which is the thirteen minutes still left in the window at 03:07. (Some APIs write the same header as a date and time instead; both forms are legal and mean the same thing — come back then.) There is nothing here to debug. There is a time to come back.

Timeouts: the Non-Answer

Sometimes nothing comes back at all. You send the request, the terminal sits there, and after a while curl gives up and tells you it timed out. That is not a status code, because a status code requires a response, and this is the case where no response arrived.

Here is the honest and slightly uncomfortable part. A timeout tells you nothing about whether your request was carried out. It may have never arrived. It may have arrived and been ignored. Or it may have arrived, been fully carried out, and had its answer die on the way back to you. From where you sit, those three look identical.

For a request that only reads data, the ambiguity costs nothing — ask again and look. For a request that creates something, it matters a great deal, and it is the reason the next page exists.

What Your Side Does

Read the body anyway. A 503 frequently explains itself, and a 500 sometimes carries a request id worth keeping. Then honor whatever the response asked of you: if Retry-After is there, that number is not a suggestion, it is the provider telling you when trying again will actually work.

If there is no such header, wait with intention rather than reflex. Try once after a short pause, and if that fails wait longer before the next attempt, and longer again after that. The word for this pattern is backoff — each retry spaced further apart than the last — and the next chapter puts it to work properly against rate limits.

And before deciding the world has ended, check the provider's status page: a page the provider maintains to say publicly whether their service is healthy. Tandem has one, and on that Sunday morning it says exactly what the response said. Two minutes there beats an hour of suspicion.

Evidence, Not Vigils

What you never do is hammer. Sixty identical requests a minute against a struggling server add load to the exact thing that is struggling, and they spend your own quota telling you the same bad news over and over. Persistence is a virtue in many places; against an overloaded service it is a contribution to the overload.

Instead, take notes while you wait. The time, the status, the request id from the body, the endpoint you called. If the trouble outlasts the posted window — if it is 03:35 and the 503 is still there — that little bundle is your escalation, and the last page of this chapter turns it into an email that gets answered on the first reply. Vera reruns her pull at 03:21 and the report never learns anything happened.

Common Confusions
  • "A 5xx means my request was wrong somehow." The request was fine and the answering side failed. Editing your request to cure a 503 is rewriting your letter because the post office is on fire — the letter was never the problem.
  • "A timeout means the request did not happen." Unknown, and that is the whole point. It may have been carried out with the answer lost on the way back. That ambiguity is what the next page is about.
  • "Retry immediately and often — persistence pays." Against an overloaded server, persistence is load. The spaced retry that honors Retry-After is also the one that succeeds soonest, so politeness and self-interest agree here.
  • "If it is broken for me it is broken for everyone." Possibly, and the status page settles it in two minutes. Checking before assuming is what separates a useful report from a panicked one.
Why It Matters
  • Telling weather from error saves hours of self-blame and pointless request-editing. It is the second half of the instinct this book keeps building: whose side is the problem on?
  • Retry-After and status pages turn an outage from a mystery into a schedule. A problem with a known end time is an inconvenience; the same problem without one feels like a crisis.

Knowledge Check

What does a 502 or 504 indicate?

  • Your request was malformed and the server could not parse it
  • A middleman could not reach or could not wait for the real server
  • Your credentials expired somewhere between sending and arriving
  • You have sent more requests this minute than your key allows

Your POST times out. What do you actually know?

  • That the request definitely did not reach the server or take effect
  • That no answer arrived, and nothing about whether it acted
  • That the request was carried out but the server is now overloaded
  • That the server replied with a 504 that curl chose not to display

A 503 arrives carrying Retry-After: 780. What is it asking of you?

  • That you make at most 780 further attempts before contacting support about it
  • That you quote the number 780 in the Authorization header of your next request
  • That you wait 780 seconds, which is thirteen minutes, before trying it again
  • That your request has been queued and will be answered within 780 seconds

Tandem returns 503s for twenty minutes past the posted maintenance window. What is the professional move?

  • Send the request in a tight loop so you catch the exact second it recovers
  • Rewrite the request with different parameters in case one of them helps
  • Escalate with the times, the statuses, and the request id you noted down
  • Assume the window was extended and wait silently until tomorrow morning

You got correct