In a Perfect World, We’d Only Need 200 and 400

The Problem: Why Are There So Many HTTP status codes and Why Are they so confusing?! I once set out to build a simple REST API. All I had to do was return a response with the right HTTP status code. Simple, right? Wrong. My first instinct was to follow the "success or failure" approach. If things worked, I’d return 200 OK. If things didn’t work, I’d return 400 Bad Request. Done. Then, reality slapped me in the face. A senior engineer came along and asked: "Why are you returning 400 when it’s clearly a 422 Unprocessable Entity? And why are you not using 409 Conflict when there’s a duplicate entry? Oh, and don’t forget 304 Not Modified for caching. Also, rate limiting? 429 Too Many Requests." And I just stood there, staring at my screen, questioning my life choices. Examples of the Madness Here’s a real-world example of how confusing HTTP status codes can be: 500 Internal Server Error: Did my backend crash? Is my database down? Or did my load balancer just decide that today was not the day? 404 Not Found: Is the endpoint missing, or is my routing broken? Or did I just typo my URL? 401 Unauthorized vs. 403 Forbidden: Ah, yes. So I’m not authorized? But wait, am I not authorized because I’m missing credentials (401)? Or do I have credentials, but I’m just not worthy (403)? 429 Too Many Requests: Ah, I see. My API is punishing me for being too enthusiastic. Why Are These Status Codes Even a Thing? At this point, you might be asking, "Why do we even need all these?" I asked the same thing. Wouldn’t it be easier if we just had: ✅ 200 OK for success❌ 400 Bad Request for failure Done. Simple. Clean. No headaches. But then reality struck again. HTTP status codes exist to help machines make decisions quickly. The Secret Behind Why This Works Browsers need caching (304 Not Modified) so they don’t waste bandwidth downloading the same thing over and over. Load balancers need to know (502 Bad Gateway) when a backend is dead so they can reroute traffic. APIs need rate limiting (429 Too Many Requests) so users don’t take down the entire system. Search engines need redirects (301 Moved Permanently) so they know where to send users. Clients need to know when to retry (503 Service Unavailable means "try again later"). By forcing clients to check the status code first instead of parsing the response body, we make APIs, browsers, and entire distributed systems faster and more efficient. The Minimal Set of HTTP Status Codes You Actually Need If we trim the fat, here’s what really matters:

Mar 20, 2025 - 09:06
 0
In a Perfect World, We’d Only Need 200 and 400

The Problem: Why Are There So Many HTTP status codes and Why Are they so confusing?!

I once set out to build a simple REST API. All I had to do was return a response with the right HTTP status code. Simple, right? Wrong.

My first instinct was to follow the "success or failure" approach. If things worked, I’d return 200 OK. If things didn’t work, I’d return 400 Bad Request. Done.

Then, reality slapped me in the face. A senior engineer came along and asked:

"Why are you returning 400 when it’s clearly a 422 Unprocessable Entity? And why are you not using 409 Conflict when there’s a duplicate entry? Oh, and don’t forget 304 Not Modified for caching. Also, rate limiting? 429 Too Many Requests."

And I just stood there, staring at my screen, questioning my life choices.

Examples of the Madness

Here’s a real-world example of how confusing HTTP status codes can be:

  • 500 Internal Server Error: Did my backend crash? Is my database down? Or did my load balancer just decide that today was not the day?
  • 404 Not Found: Is the endpoint missing, or is my routing broken? Or did I just typo my URL?
  • 401 Unauthorized vs. 403 Forbidden: Ah, yes. So I’m not authorized? But wait, am I not authorized because I’m missing credentials (401)? Or do I have credentials, but I’m just not worthy (403)?
  • 429 Too Many Requests: Ah, I see. My API is punishing me for being too enthusiastic.

Why Are These Status Codes Even a Thing?

At this point, you might be asking, "Why do we even need all these?" I asked the same thing. Wouldn’t it be easier if we just had:

✅ 200 OK for success❌ 400 Bad Request for failure

Done. Simple. Clean. No headaches.

But then reality struck again. HTTP status codes exist to help machines make decisions quickly.

The Secret Behind Why This Works

  1. Browsers need caching (304 Not Modified) so they don’t waste bandwidth downloading the same thing over and over.
  2. Load balancers need to know (502 Bad Gateway) when a backend is dead so they can reroute traffic.
  3. APIs need rate limiting (429 Too Many Requests) so users don’t take down the entire system.
  4. Search engines need redirects (301 Moved Permanently) so they know where to send users.
  5. Clients need to know when to retry (503 Service Unavailable means "try again later").

By forcing clients to check the status code first instead of parsing the response body, we make APIs, browsers, and entire distributed systems faster and more efficient.

The Minimal Set of HTTP Status Codes You Actually Need

If we trim the fat, here’s what really matters: