Live data from Hacker News

Best practices for REST API design (2020)

stackoverflow.blog

141–150 of 273 posts

Re: Best practices for REST API design (2020)

#141

Earlier quoted context omitted.

The whole point of graphQL is to allow FE teams to decide what information they need in an organizationally decoupled fashion, you haven't done that at all. Suppose FE wants another join on that object, now they must wait for you to push more code enabling those queries.

Unfortunately for graphql, the claim that backend teams need to be constantly making endpoints for other decoupled teams is not as drastic and critical as you consider it to be. Dare i even say switching to graphql and onboarding developers to graphql is a much more resource intensive process than adding another endpoint (or a couple).

> onboarding developers to graphql is a much more resource intensive process

As a BE/remote I basically taught myself most of elixir's graphQL framework in a day (wait, that was yesterday), while under feature pressure (due this afternoon), mostly by poking around and doing a bit of TDD. There are parts that I really hate about graphQL, but overall I consider it a win.

Re: Best practices for REST API design (2020)

#142

Design is hard. In the given example we work with an Article domain. Where there are Comments. Fine and totally fair. But how would you design your object graph from the bottom up? Articles and Comments is a fairly simple example. Imagine a Transaction in bank domain context. Would you have an endpoint like so? transactions/:id/acoount/:id Or perhaps transactions/:id account/:id/transactions Whatever you pick you mus…

It would be for all transactions /transactions and for transactions for a particular account /accounts/:id/transactions.

Re: Best practices for REST API design (2020)

#143

A question I’ve always had about 404 and APIs... How do you distinguish between an invalid path (no end point) and a valid path requesting a resource that doesn’t exist?

If doesn't exist means it has been removed: 410 Gone, if doesn't exist means not yet created: 404 Not Found. I can't think for other types of not existing, or why you'd need to differentiate between them.

Say I have an API with a path of /customer/.

I call /customer/235235 and customer 235235 doesn't exist. That's a 404, resource not found.

But say I make an uncaught error with the path and call /cutsomer/235235. That also is a 404, resource not found.

It really depends on what you want the word "resource" to mean.

It gets a bit more complex if you have a simplistic website with an API service both on the same server. For your users, you want a nice 404 page for mistyped or dead links. But you don't want your API also triggering that same page.

Beyond actually splitting your main web content and API into two servers, I could see returning a 400, Bad Request response for the API to avoid triggering a 404 handler. After all if you give it a customer ID in the above case that doesn't exist, it is essentially a "bad input parameter" and the error message can indicate which parameter (the customer ID) and why it's a problem (there is no such customer).

Re: Best practices for REST API design (2020)

#144

A question I’ve always had about 404 and APIs... How do you distinguish between an invalid path (no end point) and a valid path requesting a resource that doesn’t exist?

You don't

I can just see some developer going nuts and pulling out their hair because they can't figure out why a call to query a customer keeps saying the customer doesn't exist when clearly it is in the database. Until they realize they gave the URL path as "/cutsomer" instead of "/customer" in the code.

Re: Best practices for REST API design (2020)

#145
post #65

Do not use a page argument for pagination. If you have another process/client concurrently adding/removing items, then some items will be returned twice, and others will never be returned. It is better to use, for example, the ID of the last returned item as a starting point for the next query.

I'd suggest caching the result of a query that could return multiple pages, if consistency is truly important. Otherwise, I don't think it really matters which option you choose, as long as you document the behavior.

Edit: obviously the proper impl totally depends on your app. If the result set is enormous, caching doesn't make sense. If it's rapidly changing, pagination probably doesn't make sense. etc, etc.

Re: Best practices for REST API design (2020)

#146
post #138
post #65

Do not use a page argument for pagination. If you have another process/client concurrently adding/removing items, then some items will be returned twice, and others will never be returned. It is better to use, for example, the ID of the last returned item as a starting point for the next query.

If items get returned twice while iterating, then I know something got added. Manga websites do this and it's a nice unintended feature. Slicing by ID is how Github does commit history and it drives me nuts that I can't jump several pages, for example, to see when the first commit was, or to guess whereabouts some commit is given a known time range. IDs make it impossible to do anything but iterate step by step. I mu…

> If items get returned twice while iterating, then I know something got added.

Fair point. I agree, that's a nice side effect. But what if you're looking at page 1, and an item is removed from that page? Then you'll never see the first item at page 2, because it's now the last on page 1.

> Then if I want a slice from 300-8000th items, I can type exactly that in the URL.

That's a nice feature. But it can put a lot of load on your backend if you paginate over 10 of thousands of items.

Re: Best practices for REST API design (2020)

#147
post #145
post #65

Do not use a page argument for pagination. If you have another process/client concurrently adding/removing items, then some items will be returned twice, and others will never be returned. It is better to use, for example, the ID of the last returned item as a starting point for the next query.

I'd suggest caching the result of a query that could return multiple pages, if consistency is truly important. Otherwise, I don't think it really matters which option you choose, as long as you document the behavior. Edit: obviously the proper impl totally depends on your app. If the result set is enormous, caching doesn't make sense. If it's rapidly changing, pagination probably doesn't make sense. etc, etc.

But then you need to provide some kind of query ID in the the HTTP request? And if you many concurrent clients, that can be expensive in terms of RAM?

If we don't care about added items (they can be deduped client-side), and only care about removed items, maybe the backend can maintain a tombstone timestamp on each deleted item, instead of deleting them, and then the client can provide a "snapshot" timestamp in the query that can be compared with the tombstone timestamp.

Re: Best practices for REST API design (2020)

#148
post #65

Do not use a page argument for pagination. If you have another process/client concurrently adding/removing items, then some items will be returned twice, and others will never be returned. It is better to use, for example, the ID of the last returned item as a starting point for the next query.

i prefer an offset, then a crawling client can pad their requests and remove anything with a duplicate id.

That solves the problem of items added concurrently (by deduplicating them) but that doesn't solve the problem of removed items.

Re: Best practices for REST API design (2020)

#149
post #145
post #65

Do not use a page argument for pagination. If you have another process/client concurrently adding/removing items, then some items will be returned twice, and others will never be returned. It is better to use, for example, the ID of the last returned item as a starting point for the next query.

I'd suggest caching the result of a query that could return multiple pages, if consistency is truly important. Otherwise, I don't think it really matters which option you choose, as long as you document the behavior. Edit: obviously the proper impl totally depends on your app. If the result set is enormous, caching doesn't make sense. If it's rapidly changing, pagination probably doesn't make sense. etc, etc.

If consistency is really important, don't paginate on the backend at all. The only way to win is not to play the game.

That said, using “page of results preceding ” and “page of results following ” reduces obvious pagination artifacts compared to . Whether it's better to beat consumers over the head with inconsistency due to concurrent changes probably depends on the application or provide a nearer illusion of consistency probably depends on application domain and use case.

Re: Best practices for REST API design (2020)

#150
post #71

Earlier quoted context omitted.

As a user I expect that to happen. Cursors on the other hand are awful for getting to arbitrary pages, they are mostly useful for "More" links as on HN or Reddit. It's a trade-off.

I’d say they’re right: cursors are way better for an API. Pages are way better for a person. This here is about an API.

Here I think it makes sense to split the API in two classes:

1. APIs consumed by other backends lets call them API2B

2. APIs consumed by frontends lets call them API2C

In this case cursors are better for API2B but not for API2C as in case of API2C most users expect to be able to jump directly to a specific page.

At least when I am designing an API i take different decisions based on this split. For example in case of API2C I always want to see FE design even if I work on backend.

Post reply on HN