What the five status classes mean
Every HTTP response begins with a three-digit status code, and the first digit alone tells a client what kind of answer it received. 1xx is informational and means the request was received and processing continues. 2xx means the request succeeded. 3xx means further action is needed to complete it, almost always following a redirect. 4xx means the request was faulty in a way the client is responsible for. 5xx means the request looked fine and the server failed to fulfil it.
The classes exist so that a client can behave sensibly when it meets a code it has never seen. RFC 9110 requires exactly this: an unrecognised 4xx must be treated like 400 and an unrecognised 5xx like 500. That is why inventing an application-specific code in an existing class is safe while inventing a new class is not.
The 4xx and 5xx split carries real operational weight. A rise in 4xx usually points at clients, integrations or bad links; a rise in 5xx points at your own systems and is what should page someone. Miscategorising an error, most commonly by returning 500 for a request that was simply malformed, makes that signal useless.
The redirects: 301, 302, 307 and 308
The distinction that matters most is permanence, because it determines caching. A 301 Moved Permanently may be cached indefinitely, and browsers and search engines treat it as a durable move: link equity transfers and clients may stop requesting the original URL entirely. A 302 Found is temporary and is not cached by default, which is what you want for a redirect that depends on state such as login or locale.
The second distinction is method preservation, and it is the reason 307 and 308 exist. Historically clients responded to a 301 or 302 on a POST by reissuing the request as a GET, which contradicted the specification but became universal behaviour. 307 Temporary Redirect and 308 Permanent Redirect were defined to forbid that: the method and the body must be preserved. Use 307 and 308 for anything other than a GET, and 301 and 302 for plain page moves.
303 See Other is the deliberate opposite: it tells the client to follow up with a GET regardless of the original method. That is exactly the post-redirect-get pattern, where a form submission answers with 303 pointing at a result page so that a browser refresh does not resubmit the form.
The client errors people most often get wrong
401 Unauthorized is about authentication, despite its name. It means the request lacked valid credentials, and a correct 401 response must include a WWW-Authenticate header naming the scheme, for example WWW-Authenticate: Bearer realm="api". 403 Forbidden means the server understood who you are and is refusing anyway, so re-authenticating will not help. Sending 401 when the user is logged in but lacks permission causes clients to loop through a pointless login flow.
404 Not Found and 410 Gone differ in intent. 404 says the resource is not here, without committing to whether it ever was or will be again. 410 says it existed and has been deliberately removed, which tells crawlers to drop the URL rather than keep retrying. For content you have intentionally retired, 410 is the more useful answer.
422 Unprocessable Content is for a request that parsed correctly but failed business or semantic validation, which is the usual answer for a form or API payload whose fields are individually well-formed and collectively invalid. 400 Bad Request is for a request the server could not parse at all, such as malformed JSON. 429 Too Many Requests signals rate limiting and should carry a Retry-After header so the client knows how long to wait.
Server errors and the gateway family
500 Internal Server Error is the generic failure: something went wrong and no more specific code applies. It should not be the default for everything. 501 Not Implemented means the method itself is unsupported, and 505 means the HTTP version is. 503 Service Unavailable is the right answer for a deliberate outage or an overload, and it is explicitly temporary, so pairing it with Retry-After lets clients and crawlers back off intelligently rather than hammering or de-indexing.
502 Bad Gateway and 504 Gateway Timeout both come from an intermediary such as a reverse proxy, a load balancer or a CDN. 502 means the upstream returned something invalid or refused the connection, which usually means the application process is down or crashed. 504 means the upstream accepted the connection and did not answer in time, which usually means the application is alive but slow or deadlocked. That difference is the first thing to check when debugging, because it separates a dead service from a hung one.
Two codes in the 4xx range often surface from infrastructure rather than application code. 413 Content Too Large usually comes from a proxy body size limit, commonly one megabyte by default in nginx, and 431 from oversized headers, often a bloated cookie. Both are configuration issues rather than bugs in the handler.