Infra, Illustrated.
HTTP · STATUS CODE MAP

HTTP Status Codes as a City Map

Every answer over HTTP opens with a three-digit number. The first digit picks one of five districts, and each sign in a district is one code. Choose a sign to see what the server is saying, who acts next and where to look.

EXAMPLE SITE · shop.exampleFOUNDATIONAL · OPERATIONAL REFERENCEPublished Oct 13, 2026 · Reviewed Oct 13, 2026
SELECTED SIGN200 OK
a browser asking shop.example
a sign is one status code a district is one first digit the road to the selected district
HTTP status codes as a city mapA request travels from the browser to the server at the centre. Roads lead from there to five districts, one for each first digit. 1xx, The Gatehouse, not done yet: 100 Continue, 101 Switching Protocols, 103 Early Hints. 2xx, Market Square, it worked: 200 OK, 201 Created, 202 Accepted, 204 No Content, 206 Partial Content. 3xx, The Crossroads, look elsewhere: 301 Moved Permanently, 302 Found, 303 See Other, 304 Not Modified, 307 Temporary Redirect, 308 Permanent Redirect. 4xx, The Wall, fix the request: 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 405 Method Not Allowed, 409 Conflict, 422 Unprocessable Content, 429 Too Many Requests. 5xx, The Factory, the server failed: 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout. In The Factory, 502, 503 and 504 hang on the front office, which is the proxy, and 500 on the workshop behind it, which is the app.1xxThe Gatehousenot done yet2xxMarket Squareit worked3xxThe Crossroadslook elsewhere4xxThe Wallfix the request5xxThe Factorythe server failed100Continue101Switching Protocols103Early Hints200OK201Created202Accepted204No Content206Partial Content301Moved Permanently302Found303See Other304Not Modified307Temporary Redirect308Permanent Redirect400Bad Request401Unauthorized403Forbidden404Not Found405Method Not Allowed409Conflict422Unprocessable Content429Too Many Requests500Internal Server Error502Bad Gateway503Service Unavailable504Gateway Timeout
1xx · THE GATEHOUSE · NOT DONE YET

100 Continue

“Go ahead and send the rest.”

Before uploading a large photo, the browser sends only the request headers, with Expect: 100-continue. The shop answers 100, the browser sends the photo, and then the real answer arrives.

Who acts next
the client sends the body
Ask again?
not applicable; this is not a final answer
Usually written by
the server
Header to read: Expect (in the request)
100-continue
DISTRICT 1xx

The Gatehouse: not done yet

Notes handed out on the way in, before the real answer. Exactly one final answer from another district always follows.

Watch both status linescurl -i -H 'Expect: 100-continue' -d @photo.jpg https://shop.example/photos
WORTH KNOWING ABOUT 100

This lets a server refuse a huge upload before any of it is sent. A client that hears nothing should send the body anyway after a short wait, because an older box on the path may never pass the 100 along.

RFC 9110: informational 1xx ↗

THE POINT TO KEEPA 1xx is never the last word: wait for the final answer that follows it.

1xx · THE GATEHOUSE · NOT DONE YET

101 Switching Protocols

“Agreed. This connection now speaks something else.”

The shop's live chat asks to upgrade its connection to WebSocket. After the 101, the same connection stops carrying HTTP requests and carries chat messages instead.

Who acts next
both sides switch protocol
Ask again?
not applicable; this is not a final answer
Usually written by
the server
Header to read: Upgrade
websocket
DISTRICT 1xx

The Gatehouse: not done yet

Notes handed out on the way in, before the real answer. Exactly one final answer from another district always follows.

Where to see itbrowser developer tools → Network → the chat request shows 101
WORTH KNOWING ABOUT 101

Every box on the path has to pass the upgrade along. A proxy that isn't configured to do so is a common reason a WebSocket works on a laptop and fails behind a load balancer.

RFC 9110: informational 1xx ↗

THE POINT TO KEEPA 1xx is never the last word: wait for the final answer that follows it.

1xx · THE GATEHOUSE · NOT DONE YET

103 Early Hints

“Start loading these while I work.”

While the shop builds the cart page, it sends a 103 naming the stylesheet the page will need. The browser starts fetching it, and the 200 with the page follows.

Who acts next
the client may start fetching the hinted files
Ask again?
not applicable; this is not a final answer
Usually written by
the server
Header to read: Link
</app.css>; rel=preload; as=style
DISTRICT 1xx

The Gatehouse: not done yet

Notes handed out on the way in, before the real answer. Exactly one final answer from another district always follows.

Watch both status linescurl -i https://shop.example/cart
WORTH KNOWING ABOUT 103

One request can produce several status lines. A log or tool that records one number per request shows only the final answer.

RFC 9110: informational 1xx ↗RFC 8297: 103 Early Hints ↗

THE POINT TO KEEPA 1xx is never the last word: wait for the final answer that follows it.

2xx · MARKET SQUARE · IT WORKED

200 OK

“Here is what you asked for.”

The browser asks for /cart and gets the cart page.

Who acts next
the client uses the answer
Ask again?
no need
Usually written by
the app, or a cache holding its answer
DISTRICT 2xx

Market Square: it worked

The server understood the request, accepted it and carried it out. Which sign you reach says what comes back.

Print the first line of the answercurl -si https://shop.example/cart | head -1
WORTH KNOWING ABOUT 200

An app that catches its own failure and still answers 200 with {"error": "…"} in the body looks healthy to every load balancer and dashboard that reads only the number. Also, only the digits are protocol: "200 Fine" is a valid 200, and HTTP/2 sends no words at all.

RFC 9110: successful 2xx ↗RFC 9112: the HTTP/1.1 status line ↗

THE POINT TO KEEPAny 2xx says the request was carried out. It does not say the content is what you hoped for.

2xx · MARKET SQUARE · IT WORKED

201 Created

“Done, and something new now exists.”

A POST to /orders creates order 7. The Location header gives the new order's address.

Who acts next
the client uses the answer
Ask again?
no need
Usually written by
the app
Header to read: Location
/orders/7
DISTRICT 2xx

Market Square: it worked

The server understood the request, accepted it and carried it out. Which sign you reach says what comes back.

Find the new addresscurl -si -d '{"item":12,"qty":2}' https://shop.example/orders | grep -i '^location'
WORTH KNOWING ABOUT 201

A client that needs the new thing should read Location and not guess the address from the request.

RFC 9110: successful 2xx ↗

THE POINT TO KEEPAny 2xx says the request was carried out. It does not say the content is what you hoped for.

2xx · MARKET SQUARE · IT WORKED

202 Accepted

“Received. The work will happen later.”

The browser asks for a full year's sales export. The shop puts the job in a queue and answers straight away, before any of the export exists.

Who acts next
the client checks back for the result
Ask again?
no; ask for the result at the address the API gives you
Usually written by
the app
DISTRICT 2xx

Market Square: it worked

The server understood the request, accepted it and carried it out. Which sign you reach says what comes back.

What to look fora status address in the response body or Location header
WORTH KNOWING ABOUT 202

A 202 is a promise to try. The job can still fail afterwards, and HTTP has no way to send that news later, so the API has to offer somewhere to ask.

RFC 9110: successful 2xx ↗

THE POINT TO KEEPAny 2xx says the request was carried out. It does not say the content is what you hoped for.

2xx · MARKET SQUARE · IT WORKED

204 No Content

“Done. There is nothing to send back.”

DELETE /cart/items/3 removes the item from the cart. The answer ends after its headers.

Who acts next
the client uses the answer
Ask again?
no need
Usually written by
the app
DISTRICT 2xx

Market Square: it worked

The server understood the request, accepted it and carried it out. Which sign you reach says what comes back.

See the empty answercurl -si -X DELETE https://shop.example/cart/items/3
WORTH KNOWING ABOUT 204

Client code that parses every successful answer as JSON fails here, because the body is empty.

RFC 9110: successful 2xx ↗

THE POINT TO KEEPAny 2xx says the request was carried out. It does not say the content is what you hoped for.

2xx · MARKET SQUARE · IT WORKED

206 Partial Content

“Here is the slice you asked for.”

Someone skips ahead in the shop's intro video. The browser asks for just those bytes with a Range header and gets just those bytes.

Who acts next
the client uses the answer
Ask again?
no need
Usually written by
the app, a file server or a CDN
Header to read: Content-Range
bytes 0-999/48000
DISTRICT 2xx

Market Square: it worked

The server understood the request, accepted it and carried it out. Which sign you reach says what comes back.

Ask for the first 1000 bytescurl -si -r 0-999 https://shop.example/intro.mp4 | head -5
WORTH KNOWING ABOUT 206

A server is free to ignore Range and answer 200 with the whole file, so a client has to check which of the two it received.

RFC 9110: successful 2xx ↗

THE POINT TO KEEPAny 2xx says the request was carried out. It does not say the content is what you hoped for.

3xx · THE CROSSROADS · LOOK ELSEWHERE

301 Moved Permanently

“Moved for good. Use the new address from now on.”

The sale page moved from /sale to /deals. The shop answers with the new address in a Location header, and the browser sends a second request there.

Who acts next
the client asks again at the address in Location
Ask again?
yes, at the new address
Usually written by
the app or the proxy
Header to read: Location
/deals
DISTRICT 3xx

The Crossroads: look elsewhere

What you want is at another address, or already in your own cache. The client has one more step to take.

Watch both answerscurl -sIL https://shop.example/sale
WORTH KNOWING ABOUT 301

Browsers and curl turn a redirected POST into a GET here and drop its body. Browsers may also remember a 301 long after you change the server, so use 302 until you are sure of the move. They give up after 20 redirects in a row.

RFC 9110: redirection 3xx ↗Fetch standard: following a redirect ↗

THE POINT TO KEEPA 3xx is an instruction to the client, and following it is a second request the client makes.

3xx · THE CROSSROADS · LOOK ELSEWHERE

302 Found

“It is over there for now. Keep using this address.”

During a promotion, /deals sends visitors to /summer. Next week it will point somewhere else, so the browser keeps asking /deals first.

Who acts next
the client asks again at the address in Location
Ask again?
yes, at the new address
Usually written by
the app or the proxy
Header to read: Location
/summer
DISTRICT 3xx

The Crossroads: look elsewhere

What you want is at another address, or already in your own cache. The client has one more step to take.

Print where it pointscurl -sI https://shop.example/deals | grep -i '^location'
WORTH KNOWING ABOUT 302

The method changes just as it does for 301: a redirected POST arrives as a GET. Use 307 when it must stay a POST.

RFC 9110: redirection 3xx ↗Fetch standard: following a redirect ↗

THE POINT TO KEEPA 3xx is an instruction to the client, and following it is a second request the client makes.

3xx · THE CROSSROADS · LOOK ELSEWHERE

303 See Other

“Done. Now go and look at this page.”

The checkout form is posted, the shop takes the order, and it redirects to /receipt/7. Refreshing the receipt repeats a GET, so the order isn't submitted twice.

Who acts next
the client asks again at the address in Location
Ask again?
yes, at the new address
Usually written by
the app
Header to read: Location
/receipt/7
DISTRICT 3xx

The Crossroads: look elsewhere

What you want is at another address, or already in your own cache. The client has one more step to take.

Follow a POST and print the final methodcurl -sL -o /dev/null -w '%{method} %{url_effective}\n' -d a=1 https://shop.example/checkout
WORTH KNOWING ABOUT 303

The second request is a GET by design, whatever the first one was. This is the usual answer to a form submission.

RFC 9110: redirection 3xx ↗

THE POINT TO KEEPA 3xx is an instruction to the client, and following it is a second request the client makes.

3xx · THE CROSSROADS · LOOK ELSEWHERE

304 Not Modified

“Nothing changed. Use the copy you already have.”

The browser kept the shop's logo along with its version label, "v7". On the next visit it asks for the logo only if the label has changed. It hasn't, so the shop sends headers and no image.

Who acts next
the client shows its stored copy
Ask again?
no need
Usually written by
the app, a proxy or a CDN
Header to read: If-None-Match (in the request)
"v7"
DISTRICT 3xx

The Crossroads: look elsewhere

What you want is at another address, or already in your own cache. The client has one more step to take.

Ask conditionallycurl -sI -H 'If-None-Match: "v7"' https://shop.example/logo.png
WORTH KNOWING ABOUT 304

This is why 304 lives at the crossroads: the answer is elsewhere, and elsewhere is the browser's own cache. It saves the transfer and not the round trip.

RFC 9110: redirection 3xx ↗RFC 9110: conditional requests ↗

THE POINT TO KEEPA 3xx is an instruction to the client, and following it is a second request the client makes.

3xx · THE CROSSROADS · LOOK ELSEWHERE

307 Temporary Redirect

“Over there for now. Repeat the request exactly.”

The checkout form is posted to /checkout while payments are being served from /pay. The browser sends the same POST, with the same body, to /pay.

Who acts next
the client asks again at the address in Location
Ask again?
yes, at the new address
Usually written by
the app or the proxy
Header to read: Location
/pay
DISTRICT 3xx

The Crossroads: look elsewhere

What you want is at another address, or already in your own cache. The client has one more step to take.

Follow a POST and print the final methodcurl -sL -o /dev/null -w '%{method}\n' -d a=1 https://shop.example/checkout
WORTH KNOWING ABOUT 307

307 exists because clients rewrite the method on 302. The client must not change it here.

RFC 9110: redirection 3xx ↗

THE POINT TO KEEPA 3xx is an instruction to the client, and following it is a second request the client makes.

3xx · THE CROSSROADS · LOOK ELSEWHERE

308 Permanent Redirect

“Moved for good. Repeat the request exactly.”

The shop's API moved from /api/orders to /v2/orders. A POST to the old address is sent again, unchanged, to the new one.

Who acts next
the client asks again at the address in Location
Ask again?
yes, at the new address
Usually written by
the app or the proxy
Header to read: Location
/v2/orders
DISTRICT 3xx

The Crossroads: look elsewhere

What you want is at another address, or already in your own cache. The client has one more step to take.

Watch both answerscurl -sIL -X POST https://shop.example/api/orders
WORTH KNOWING ABOUT 308

It is to 301 what 307 is to 302. Like a 301, it may be remembered by browsers and caches, so it is hard to take back.

RFC 9110: redirection 3xx ↗

THE POINT TO KEEPA 3xx is an instruction to the client, and following it is a second request the client makes.

4xx · THE WALL · FIX THE REQUEST

400 Bad Request

“I can't read this request.”

An order arrives with its JSON cut off partway through. The shop can't parse it, so it never gets as far as thinking about an order.

Who acts next
whoever sent the request
Ask again?
not until the request changes
Usually written by
the app, or a proxy that can't parse the request
DISTRICT 4xx

The Wall: fix the request

The server looked at the request and found the problem in it: who is asking, where, or what was sent. It turns the same request back the same way every time.

Read the explanation in the bodycurl -s -H 'Content-Type: application/json' -d '{"item": 12,' https://shop.example/orders
WORTH KNOWING ABOUT 400

Many APIs answer 400 for any invalid input, not only for unreadable requests. The response body normally says what was wrong.

RFC 9110: client error 4xx ↗

THE POINT TO KEEPA 4xx fails the same way until the request changes. Only 429 is fixed by waiting.

4xx · THE WALL · FIX THE REQUEST

401 Unauthorized

“I don't know who you are.”

A request for /account arrives with no login. The shop refuses and names the kind of login it accepts.

Who acts next
whoever sent the request
Ask again?
yes, with valid credentials
Usually written by
the app, or an authenticating proxy
Header to read: WWW-Authenticate
Bearer realm="shop"
DISTRICT 4xx

The Wall: fix the request

The server looked at the request and found the problem in it: who is asking, where, or what was sent. It turns the same request back the same way every time.

See the challengecurl -si https://shop.example/account | head -3
WORTH KNOWING ABOUT 401

The name says unauthorized and the meaning is unauthenticated. The test that separates it from 403: could logging in change the answer?

RFC 9110: client error 4xx ↗RFC 9110: WWW-Authenticate ↗

THE POINT TO KEEPA 4xx fails the same way until the request changes. Only 429 is fixed by waiting.

4xx · THE WALL · FIX THE REQUEST

403 Forbidden

“I understood, and the answer is no.”

Maya is logged in and asks for /admin. Maya's account is not an admin, so sending the same credentials again changes nothing.

Who acts next
whoever sent the request
Ask again?
not with the same credentials
Usually written by
the app, or a firewall in front of it
DISTRICT 4xx

The Wall: fix the request

The server looked at the request and found the problem in it: who is asking, where, or what was sent. It turns the same request back the same way every time.

Check which box refusedcompare the proxy's log with the app's log for that request
WORTH KNOWING ABOUT 403

A 403 is not always about your account. A firewall can answer 403 for a blocked address or a request that looks like an attack, and then the app never sees it. A server may also answer 404 in place of 403 to avoid confirming that a private page exists.

RFC 9110: client error 4xx ↗

THE POINT TO KEEPA 4xx fails the same way until the request changes. Only 429 is fixed by waiting.

4xx · THE WALL · FIX THE REQUEST

404 Not Found

“Nothing is at this address.”

A typo sends the browser to /crat. The shop has no page there.

Who acts next
whoever sent the request
Ask again?
not until the request changes
Usually written by
the app, or a proxy with no rule for the path
DISTRICT 4xx

The Wall: fix the request

The server looked at the request and found the problem in it: who is asking, where, or what was sent. It turns the same request back the same way every time.

Check the exact path that was sentcurl -si https://shop.example/crat | head -1
WORTH KNOWING ABOUT 404

When the proxy writes the 404, the path may be right and the routing wrong, and the app's log is empty. A 404 doesn't say whether the page ever existed, and caches may store it, so a CDN can keep answering 404 for a file that was missing only during a deploy.

RFC 9110: client error 4xx ↗RFC 9110: status codes ↗

THE POINT TO KEEPA 4xx fails the same way until the request changes. Only 429 is fixed by waiting.

4xx · THE WALL · FIX THE REQUEST

405 Method Not Allowed

“This address exists. That action isn't offered on it.”

A DELETE is sent to /orders. Orders can be read or added there, and the list itself can't be deleted.

Who acts next
whoever sent the request
Ask again?
not until the request changes
Usually written by
the app
Header to read: Allow
GET, POST
DISTRICT 4xx

The Wall: fix the request

The server looked at the request and found the problem in it: who is asking, where, or what was sent. It turns the same request back the same way every time.

See which methods workcurl -si -X DELETE https://shop.example/orders | grep -i '^allow'
WORTH KNOWING ABOUT 405

A request names a place, the path, and an action, the method. 404 is about the place and 405 about the action, and a 405 has to list the actions that are allowed.

RFC 9110: client error 4xx ↗

THE POINT TO KEEPA 4xx fails the same way until the request changes. Only 429 is fixed by waiting.

4xx · THE WALL · FIX THE REQUEST

409 Conflict

“Valid, but it clashes with how things are now.”

An order for item 12 arrives a moment after the last one sold. Nothing is wrong with the request itself.

Who acts next
whoever sent the request
Ask again?
after loading the current state and deciding again
Usually written by
the app
DISTRICT 4xx

The Wall: fix the request

The server looked at the request and found the problem in it: who is asking, where, or what was sent. It turns the same request back the same way every time.

Read what it conflicts withthe response body
WORTH KNOWING ABOUT 409

Sending the identical request again usually conflicts again. The client has to look at the current state first.

RFC 9110: client error 4xx ↗

THE POINT TO KEEPA 4xx fails the same way until the request changes. Only 429 is fixed by waiting.

4xx · THE WALL · FIX THE REQUEST

422 Unprocessable Content

“Readable, and the values make no sense.”

An order arrives as well-formed JSON asking for a quantity of -3.

Who acts next
whoever sent the request
Ask again?
not until the request changes
Usually written by
the app
DISTRICT 4xx

The Wall: fix the request

The server looked at the request and found the problem in it: who is asking, where, or what was sent. It turns the same request back the same way every time.

Read which field failedcurl -s -H 'Content-Type: application/json' -d '{"item":12,"qty":-3}' https://shop.example/orders
WORTH KNOWING ABOUT 422

Three refusals at three depths: 400 could not read the request, 422 read it and found the values wrong, 409 found the values fine and the current data in the way.

RFC 9110: client error 4xx ↗

THE POINT TO KEEPA 4xx fails the same way until the request changes. Only 429 is fixed by waiting.

4xx · THE WALL · FIX THE REQUEST

429 Too Many Requests

“Too many requests from you. Slow down.”

A script checking prices speeds up past the shop's limit. The shop refuses the extra requests and says how long to wait.

Who acts next
whoever sent the request
Ask again?
yes, after waiting
Usually written by
a rate limiter in the app, the proxy or a CDN
Header to read: Retry-After
30
DISTRICT 4xx

The Wall: fix the request

The server looked at the request and found the problem in it: who is asking, where, or what was sent. It turns the same request back the same way every time.

Find the waitcurl -sI 'https://shop.example/search?q=mug' | grep -i '^retry-after'
WORTH KNOWING ABOUT 429

Retry-After is optional. When it is missing, wait longer after each refusal and add some randomness, so that many limited clients don't all return in the same second.

RFC 6585: 429 Too Many Requests ↗RFC 9110: Retry-After ↗

THE POINT TO KEEPA 4xx fails the same way until the request changes. Only 429 is fixed by waiting.

5xx · THE FACTORY · THE SERVER FAILED

500 Internal Server Error

“Something broke in here.”

The shop's code hits a case it does not handle while building the cart. Its framework catches the crash and answers 500, and the proxy passes that answer back unchanged.

Who acts next
whoever runs the server
Ask again?
possibly later; nothing in the request needs fixing
Usually written by
the app
DISTRICT 5xx

The Factory: the server failed

The request was fine and the city's own machinery was not. Two buildings write codes here: the front office, which is a proxy, and the workshop behind it, which is the app.

Find them in an access logawk '$9 ~ /^5/' access.log
WORTH KNOWING ABOUT 500

The page a visitor gets is vague on purpose, since a stack trace would tell an attacker about the code. The useful detail is in the app's log for that moment.

RFC 9110: server error 5xx ↗

THE POINT TO KEEPA 5xx sends you to the server's logs, and a 502 or 504 points one hop behind the box that wrote it.

5xx · THE FACTORY · THE SERVER FAILED

502 Bad Gateway

“The box behind me gave a bad answer.”

The proxy passes the request to the app and gets back half a reply, nonsense, or a closed connection. It can't forward that, so it writes an answer of its own.

Who acts next
whoever runs the server
Ask again?
often, after a short wait
Usually written by
the proxy, about the app
DISTRICT 5xx

The Factory: the server failed

The request was fine and the city's own machinery was not. Two buildings write codes here: the front office, which is a proxy, and the workshop behind it, which is the app.

Compare two logsproxy: 502 at 10:02:11 · app: restarted at 10:02:10
WORTH KNOWING ABOUT 502

The app this code describes never writes it. Look for app crashes and restarts at that time, or an app that closes idle connections sooner than the proxy expects.

RFC 9110: server error 5xx ↗AWS: troubleshoot Application Load Balancers ↗

THE POINT TO KEEPA 5xx sends you to the server's logs, and a 502 or 504 points one hop behind the box that wrote it.

5xx · THE FACTORY · THE SERVER FAILED

503 Service Unavailable

“Nobody can take this right now.”

The proxy has no copy of the app it can send to: they are starting up, failing health checks, or full. It answers without the request reaching any of the shop's code.

Who acts next
whoever runs the server
Ask again?
yes, after waiting
Usually written by
the proxy, or an overloaded app
Header to read: Retry-After
120
DISTRICT 5xx

The Factory: the server failed

The request was fine and the city's own machinery was not. Two buildings write codes here: the front office, which is a proxy, and the workshop behind it, which is the app.

Check what the proxy can reachthe health-check status of each app instance
WORTH KNOWING ABOUT 503

Serve a maintenance page with 503 and not 200, so that clients, monitors and crawlers know the state is temporary.

RFC 9110: server error 5xx ↗RFC 9110: Retry-After ↗AWS: troubleshoot Application Load Balancers ↗

THE POINT TO KEEPA 5xx sends you to the server's logs, and a 502 or 504 points one hop behind the box that wrote it.

5xx · THE FACTORY · THE SERVER FAILED

504 Gateway Timeout

“The box behind me took too long.”

The app has the request and is still busy when the proxy's 60-second timer runs out. The proxy stops waiting and answers 504. The app may go on to finish the work.

Who acts next
whoever runs the server
Ask again?
with care: the work may have been done
Usually written by
the proxy, about the app
DISTRICT 5xx

The Factory: the server failed

The request was fine and the city's own machinery was not. Two buildings write codes here: the front office, which is a proxy, and the workshop behind it, which is the app.

Compare two logsproxy: 504 at 10:02:11 · app: that request still running
WORTH KNOWING ABOUT 504

After a 504 on a POST, the order may have been saved, and sending it again creates a second one. GET, PUT and DELETE are safe to repeat. The 60 seconds is an example and also the default in nginx and on an AWS Application Load Balancer. If the client gives up first, no answer is sent at all, and nginx records its own 499 in the log.

RFC 9110: server error 5xx ↗RFC 9110: idempotent methods ↗AWS: troubleshoot Application Load Balancers ↗nginx: proxy_read_timeout ↗nginx source: the 499 log code ↗

THE POINT TO KEEPA 5xx sends you to the server's logs, and a 502 or 504 points one hop behind the box that wrote it.