I need to implement the following scenarios at the server:

  1. User sent too many answers in a given amount of time, for example, it can't submit more than 3 posts within an hour.
  2. User sent answer with the same text already, to prevent spamming.

My question is what is the correct way to implement client/server communication? Should the server return some kind of error, for example, 429 and 409, or return code 200 and then details of the conflict? I argue with my manager that errors should be returned. He says that error is something that we don't expect to happen, happened, but in this scenario we totally expect it.

  • 5
    Http doesn’t have errors. You get a status. Your manager is wrong.
    – gnasher729
    Commented Aug 8, 2022 at 18:47
  • @gnasher729 And status codes in the 400 and 500 blocks are explicitly for indicating client and server errors, respectively.
    – Ray
    Commented Aug 8, 2022 at 21:26
  • Ray, and there you put yourself in the wrong frame of mind. They are all status codes.
    – gnasher729
    Commented Aug 9, 2022 at 6:34
  • Depending on how paranoid you are, to counter spamming you may want to return a response in the 100 range while just ignoring the duplicate and maybe not serve the IP for a minute or so. To valid users there would be no problem (they are not supposed to redo anything, their input has already been processed). Commented Aug 10, 2022 at 15:55

3 Answers 3


Your manager is conflating an unexpected error with a willful refusal by the application to perform a requested action. What he says is correct about the former, but not the latter.

Anything that's not a 500 is an intentional message that is being returned by the API to the user, and therefore is not an unexpected error. The manager's statement is correct about unexpected errors, but he's mislabeling conscious refusals as if they're unexpected.

It may be a semantical issue. Since your manager seems to think "error" refers to unexpected failures, try communicating with them in their own lingo. Don't refer to conscious refusals as an "error", but rather as a "negative response" or a "rejected request". You may find them more willing to listen to you once you use the words the way they use them.

However, I cannot tell you how to convince your manager. I don't know why they're taking the stance that they are, nor if anything will be able to sway their current idea.

What I would do here is to work through your manager's example, because I suspect you can Socratically bring him to your goal. Something along the lines of:

DEV So tell me, the conflict details when we return a 200, what would they look like?
MAN Well, they should explain the reason why something failed.
DEV And this should also indicate which kind of failure happened?
MAN Yes, because this gives the requester the information they need.
DEV This means we're going to need a list of kinds of failures that could occur, so that the requester can respond appropriately to the specific kind of failure that was encountered.
MAN Yes.

At this point, you can showcase that this is precisely what HTTP status codes are built to do. The message that's being returned can always be chosen as you please; but the HTTP status code that you attach to this message is simply a standardized "kind of failure" that helps the requester quickly categorize what kind of failure was encountered (Did it work? Was it my fault? Was is the API's fault? Was I not allowed to access this endpoint? ...)

We made a universally agreed upon list of codes that everyone uses, so that everyone who can write software doesn't have to learn every API's own custom error codes, because it'd be an unnecessary hassle to express the same kinds of failures in individually unique ways.

If your manager still doesn't budge; maybe try asking them for information on their solution. Why would the arbitrary "failure code" be better than the universal HTTP status code? What would happen differently if you instead used the HTTP status code?
Listen to your manager, understand their reasoning, try to explain why you can achieve the same goal using the more standardized HTTP status codes.

But I want to reiterate that I cannot guarantee that your manager is willing to listen to your input, or that they even have a reason for their choice (they may be parroting existing knowledge with no intent to have it be put under a microscope). Good luck.


The HTTP protocol has a specific code for rate limiting 429.

Non-protocol errors should return 500 with a reason, which your client can then turn into an exception.

Here though I would simple silently drop the duplicate

The problem with returning a success object which encapsulates many possible results is that every call to the API has to be followed by a big if block which tries to work out what happened.

The problem with using codes for non-protocol errors is what happens when you get the actual protocol error


The HTTP standard describes the status classes this way:

  • 1xx (Informational): The request was received, continuing process.
  • 2xx (Successful): The request was successfully received, understood, and accepted.
  • 3xx (Redirection): Further action needs to be taken in order to complete the request.
  • 4xx (Client Error): The request contains bad syntax or cannot be fulfilled.
  • 5xx (Server Error): The server failed to fulfill an apparently valid request.

Although two of the names include ‘Error’, none of the descriptions do, so maybe you could draw your manager's attention to those, and explain your choices in those terms?

In both the cases you describe, you won't be accepting the requests, and so a 2xx return is clearly inappropriate. And although the requests may individually be well-formed, you're treating them as invalid and refusing to fulfil them because of their rate or repetition — which is a client-side issue, falling squarely into the 4xx class. (And, as you say, 429 Too Many Requests looks like a very good fit.)

To be even less technical, those classes could be rephrased as:

  • 1xx: “Hang on…”
  • 2xx: “Done!”
  • 3xx: “Try over there.”
  • 4xx: “Your bad!”
  • 5xx: “My bad!”

Sending too many requests and/or repeating them is clearly a mistake by the client, so the server is justified in responding “Your bad!”

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.