🦆 Dialogue

Good Banter Not Found

Duck is typing on a laptop when Tortoise arrives.

Tortoise: Good day, Duck.

Duck: Good day, Tortoise. What a splendid day it is. I see that you are alone?

Tortoise: Indeed. I tried reaching the author but he couldn't be found.

Duck: Ah, a regrettable scenario. But not one that is worthy of panic.

Tortoise: Curious that you were to say that, as I have been thinking of REST API design recently.

Duck: Oh, you too. For you see, I am working on such an API myself. Would you like to see it?

Tortoise: Not right now, although I did show the author mine, as I wanted his opinion on something.

Duck: Oh, do tell.

Tortoise: Well, this API deals with users, you see. And some users pay for the service, and some don't. And I've been tasked with coding an endpoint that'll answer which is which.

To do this, the service is to receive a user ID, and if the user is paying, it is to return the billing information along with a 200 OK.

Duck: Okay, that's pretty straightforward.

Tortoise: But what if the user is not a customer? What should the API return then?

Duck: Well, I'd imagine a 404 Not Found would do.

Tortoise: That's what the author suggested, but when I proposed this to the team, they were unhappy.

Duck: Unhappy, how?

Tortoise: They told me 404 Not Found should be reserved for errors. They said that they've got monitoring in place to catch these errors, and if I were to use it to signal a non-paying user, it'll throw off all these alarms.

Duck: Ah, yes. The "only 200 OK is okay" approach to monitoring. Understandable.

Tortoise: Oh, so you agree with their concerns?

Duck: Well, I said I understand them. For there are a number of 4xx error codes that are worthy of knowing about sooner rather than later. A significant jump in 401 Unauthorized may be of interest to these operators.

Tortoise: I guess. But isn't that what the 404 is for? Just because it can't be found doesn't mean that it's an error.

Duck: Yes, but at the same time, just because it may not be an error, doesn't necessarily mean it never is. Should a deployment go bad, and a URL is miss-configured, wouldn't you want to know straight away?

Tortoise: That's the argument they made, and I don't have a good counter. Using 404 Not Found feels right to me. It's REST-y. But I also understand their concerns about the monitoring. Oh, Mr D. I'm at a loss of what to do.

Duck: Well, some practical thinking may be worth considering. I assume you are using JSON, right?

Tortoise: Yes, that's correct.

Duck: So could you, for example, return an empty JSON object if the billing information is not found? Or maybe a boolean saying whether billing information exists or not, along with the information is available? Maybe a pattern along the same lines if multiple users are required, and if none of them are paying, you can simply return an empty array. Each could be done with a 200 OK response.

Of course, it may not be true to the idea of REST. But such is the limitations of using error codes for both business logic, such as saying a user is not paying; and control logic, such as when the endpoint is misconfigured.

Tortoise: I see. Well this has been enlightening. Thank you, Mr. D. By the way, was this the same problem you were seeing?

Duck: Oh, no. For you see, I took the bold step of shaking off REST in favour of gRPC.

Tortoise: Really? gRPC?

Duck: Yes. It eliminates the problem entirely, as it separates the absence of something (NOT_FOUND) from the absence of the service itself (UNIMPLEMENTED, INTERNAL).

Tortoise: Oh, how cleaver of you! I wonder if I can convince my team to switch. What an enviable position to be in.

Duck: Well, the envy may be all mine. For I am having a devil of a time trying to get the code generator to work. And when you are tasked with debugging an endpoint that is producing an incorrect response, and all you see is unreadable binary data; well, you may be singing a different tune.

Tortoise: Well, I will sure be singing a different tune as I head off home and ponder the suggestions you gave me. I will leave you to your errant tool chain. Good day, Duck.

Duck: Good day, Tortoise.