Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Let's stop building APIs around a network hack (2017) (apisyouwonthate.com)
103 points by goranmoomin on April 25, 2021 | hide | past | favorite | 94 comments


Is the author somehow implicitly assuming that APIs are only to be used between microservices in the same data center or something?

As far as I can see, the argument is "http2 removes handshake overhead and therefore you don't need to combine multiple things in a single response anymore".

If my request takes a second to go around the world and back, how does http2 help me? It's very weird to me to read an article about API design, written in an expert tone, that does not address this.


There's a long list of API problems not addressed by HTTP/2, because HTTP/2 set out to make sites faster, it didn't set out to make APIs more "RESTful".

Most advice I've heard from REST aficionados tends to be terrible for simplicity, correctness and performance. All in favor of an abstract set of goals, most of which never materialize. This is no exception.


As a consultant I meet a lot of people who think the goals of REST are pointless and have created an absolute shitshow of poor API design, reinventing loads of wheels and getting to a point they had to get me to come in. Usually explaining the background for why those goals are not pointless is the first step to unfucking their API ecosystem.

https://apisyouwonthate.com/blog/rest-and-hypermedia-in-2019

That's a post which aims to explain the tangible benefits of each step, but I've got plenty more articles explaining when REST is overkill and simple RPC would be a better fit.


Thanks I was going to make the same comment but felt a bit of imposter syndrome as someone who has picked up http and networking as I’ve gone along. But latency is always on my mind!

Articles like this talk about a world I don’t understand anyway. It’s like the rest/hateois etc. stuff. I just make an MVC action that does what I need in a way that makes sense and call it from the browser. If shit is slow, I profile it. No highfalutin design philosophy!


RPC thinking is one way of doing things, but not making a call is quicker than making a call. Took me a while to figure that one out too. If this article hasn't helped, see if fastly can make some of these points better.

https://www.fastly.com/blog/optimise-api-cache-improved-perf...


In addition, database accesses aren't free either.

Both in terms of latency (to be fair, probably pretty small in comparison), and in terms of knowing that all the data you fetched is consistent (because you fetched it in the same transaction).


The author specifically talks about browser support so I guess not. Given they are talking from the context of a large modern company (however you want to put that) I doubt they have to worry about users communicating with a server on the other side of the world.


As far as I can tell, eg by the extremely slow speed of the Stripe dashboard from Europe, even the most "modern" companies struggle to get their data close enough to the users that network latency no longer matters. It's a lovely ideal but I know few companies that have achieved it.

Sure, edge computing is a thing but if all the edge workers still need to go to some read replica database at least half a continent away, then in the end the 1+N requests the author suggests aren't going to get you very far.


Which modern company am I writing from? WeWork? Mate that place was a global shitshow. Funny backstory if you're interested.

https://phil.tech/2020/prioritizing-api-ecosystem-maturity/

No my article was not ignoring the concept of latency. Let fastly try and make the same points better.

https://www.fastly.com/blog/optimise-api-cache-improved-perf...


Hi, I am not assuming all microservices are in the same data center.

Your reply assumes that API requests need to be made in sequence. If you need 3 resources, and you make 3 requests, you are not waiting for 1 then 2 then 3. 1 and 2 and 3 are all coming back along the multiplexed connection and none are blocking the other. That is generally what a lot of compound documents are doing, but sure the article also talks about when you need to know some information from 1 before you can call 2 or 3.

- Server Push - since axed from some browsers, but the idea there is to proactively push the resource to you before you request it, because you know people often request Bar after requesting Foo. That means its not 1s it could be 100ms or less. The GraphQL community took this idea and created @defer.

- If people ALWAYS need to request 1 and 2 and 3, that API sounds like it was overly normalized and not too well planned. Maybe its more of a "Data Store" than an API.

It also talks about how by making endpoints smaller and more targeted, the cachability of one resource does not impact another, so you dont need to wait 1s for each requests, you just skip a lot of the requests. This article covers a lot of the same points.

https://www.fastly.com/blog/optimise-api-cache-improved-perf...


I think there is still latency to consider, especially if you have users around the world.

If you fetch invoices, and after receiving them you fetch ids of order items, and only after that you fetch actual order items, it will take 3x longer, than if you fetch everything in a single request. This can mean it could take 3 seconds to get the result, instead of 1 second with GraphQL.


And there's something to be said for batching -- if instead of requesting each resource individually, you ask for all of them simultaneously, the backend can see that context and fetch that data more efficiently.

In something truly RESTful (with HATEOAS and media types and all that jazz), the links between resources are only discoverable dynamically, and the client traverses that resource graph interactively. As the article explains, that works a lot better when you aren't scared of the per-request network overhead. But it still fundamentally limits the amount of context provided to the server on each interaction, preventing the server from optimizing for each request beyond guessing and pre-fetching what it thinks a client will need. (And the pre-fetched data has to live somewhere, meaning you've just created a cache and all its concomitant issues.)

Taking GraphQL as an alternative, the resource graph is statically known -- you can effectively fetch the schema just once. You can then traverse through many resource relationships and fetch many disparate units of data in a single request, and the backend can see that structure and decide how to efficiently gather all of that data.

Even besides the interaction context, doing REST properly (instead of a faux-REST actually-RPC HTTP API) can be pretty challenging. How many REST APIs are founded on media types instead of statically-determined URLs and methods? [0] If you're just doing HTTP RPC, you more-than-likely have a statically defined API schema, but no way to leverage that static knowledge for efficiency. (Instead you get clients coupling to the specific API endpoints instead of to the media types, making it not just static but also rigid.)

Also, HTTP/2 Push (mentioned in the article) seems to be in a weird place right now. [1]

[0] https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypert...

[1] https://evertpot.com/http-2-push-is-dead/


This is especially true since HTTP/2 uses TCP, and TCP is designed to interpret flaky wifi or cellular connections as congestion and become unusably slow. It's a fairly common situation in which you don't want to pay for additional round trips.


Isn't that handled with layer 2 retransmissions now?


Partially. There are local (L2) and fast re-transmit with ARQ [1] and HARQ [2] (at least in cellular, which I know, but I guess Wifi likely has both too), and it can help hide some packet loss to the upper layers. But this still creates added delay, which is seen by TCP as more RTT jitter, with a bad impact on performance. Also, if the link degrades really badly TCP will definitely see more congestion and loss.

So yes, the L2 will do all it can do hides wireless issues to the upper layers. But it cannot make miracles and wireless is still a challenging medium for end-to-end congestion control. There's still work at the TCP (or let's say end-to-end congestion control layer, with QUIC) to improve things, see BBRv2 for example. It's an active area, and any new generation tends to push the current state of the art.

[1] https://en.wikipedia.org/wiki/Automatic_repeat_request [2] https://en.wikipedia.org/wiki/Hybrid_automatic_repeat_reques...


> I think there is still latency to consider, especially if you have users around the world.

you speak like there's anything that exists outside of a 70km-long band in California


Not the OP but one option that HTTP/2 makes possible is to pipeline the requests.

    GET /invoices?invoicesQuery=criteria
    GET /invoices/orders?invoicesQuery=criteria
This doesn't take longer than graphql (because you're not waiting for the first response) and is a lot simpler.


How does that work when the second request depends on the results of the first request?


It doesn't. But graphql doesn't help in that case either.


You'd get the order(s) embedded with their invoice in GraphQL in a single request, applying the criteria to the invoices. Or you'd get orders matching the criteria with its invoice(s) inline. Doing two requests would be way more complicated for the developer to write.


Nonsense. As someone who's spent the last year and a half working with Shopify's API, it's far more complex to formulate a single request and then extract all the parts out of it. Especially if there's any kind of pagination involved.

Shopify's REST API is way easier to use, it's just slower. If pipelining solved the latency issue, it would be an all round superior experience.


Relating to the article, there is an (unfortunate) ongoing discussion around removing server push from Chrome/Blink/Chromium: https://groups.google.com/a/chromium.org/g/blink-dev/c/K3rYL...


Huh, that seems weird to me. _Obviously_ push would go almost nowhere in 5 years. Hell, HTTP/2 itself is still extremely new. Server push requires people to totally redesign how their infrastructure works, because their web server needs knowledge about the application.

I would expect server push to be basically unused until something comes around to automate it. It seems totally plausible to me, for example, that NGINX might add some logic to automatically keep track of which resources are requested after which other resources, and, for example, notice that "/style.css" is requested after "/" 99.9% of the time, and therefore automatically push the stylesheet.

It says a lot about Google if their approach to this stuff is to build something which requires the entire world of web servers to adapt, and then rip out the feature if it doesn't take off right away. If they were serious about it, getting everyone to restructure how their infrastructure works should've been treated as a decades-long project.

This just reinforces my existing view of not trusting Google for anything important. They just can't keep at a project. Imagine being the sucker who suggested that a business should spend a load of time restructuring their back-end infrastructure to support server push, just for Google to rip it out.


Yup, push is basically dead.


I don't think so. Chromium walked back their plans to deprecate it, and it's not leaving the IETF RFC for HTTP/2, and lots of people still like it.


Lots of talk why you don’t really need to have compound documents anymore, but no real arguments why compound documents are bad. If your server and client architectures are somewhat sane adding a compound on-load resource is cheap and I don’t see many downsides. Maybe even pack them into your initial HTML.


There's loads of problems and I've been talking about them all through a series of blog posts and talks, I just didn't cover it here.

The main problem is that tertiary data slows down primary data.

Put simply, when you request 3 things, it might take a little while for the server to find process the response, create all the JSON, shove it all over the wire, and be picked up by your client application.

The user has been sat there waiting for all three things to come back at once.

Real world example: a social network full of posts and images is failing to load because the application wanted to know if there was any space left in a meeting room nearby.

If you have 3 different things they probably have different cacheability, so let them declare their own cacheability and let the client only bother fetching them if they need to. Show the things you have when you get them. Progressively enhance the page. Don't just show nothing.

There's a lot of solutions to various problems with compound document systems like JSON:API and I've written about those too: https://apisyouwonthate.com/blog/making-the-most-of-jsonapi

But the core purpose of compound documents was the same thinking as CSS combination and Image Sprites, most of which have gone away now, and I think compound documents should too. They were a handy hack that had downsides and its no longer necessary to mess with them.


This article is a bit misguided, and contains multiple fundamental missunderstandings, first no history:

You need to know the mess that was SOAP before you go into REST, like you need to know about XML before you criticize JSON.

JSON is not a good place to put anything but data, to specify an API with a meta language has been disproven by SOAP already.

My approach to end all API fragmentation is to simply use JSON over HTTP with minimalism!

I do not conform to REST, but instead exclusively use GET and POST and return 200 everywhere and handle everything manually from there.

I also make HTML forms to all API entrypoints so you can test and learn how the API works by browsing and viewing source.

http://root.rupy.se


I’m pretty sure you just described GraphQL.

All errors are 200 unless they are HTTP errors. The backend error is under the errors key in the json.

All post requests.


He just described, well, most web APIs. Client POSTs to some endpoint, the server responds with 200 and a payload. Application-level errors are part of the payload.

Trying to merge the application API and HTTP concepts (like HTTP methods and HTTP response codes) seems to mostly just be a REST thing. Most other APIs treat HTTP as a transport layer in my experience.


Ignoring all the layers of HTTP to use it as a dumb tunnel is a really effective way of forcing everyone to reinvent a lot of wheels at every phase of the interaction. A lot of people do it, its usually a brittle and expensive waste of time.


Should add the date to the title: (2017)


"HTTP/1.1 actually solved this with Connection: keep-alive, but not many people seem to use that.

They don't? I'd assumed that was essential to anything that did a lot of back and forth transactions. And you certainly don't have to do a DNS lookup for each call.


Idk. It requires server side resources to keep the connection open, isn't it? I think nginx keeps them alive by default up to a certain limit.


This is wrong. HTTP/1.0 had a keep-alive header field as mentioned in the HTTP/1.1 RFC: https://tools.ietf.org/html/rfc7230#appendix-A.1.2

But in HTTP/1.1 that's the default: https://tools.ietf.org/html/rfc7230#section-6.3

   o  If the received protocol is HTTP/1.1 (or later), the connection will persist after the current response; else,

   o  If the received protocol is HTTP/1.0, the "keep-alive" connection
      option is present, the recipient is not a proxy, and the recipient
      wishes to honor the HTTP/1.0 "keep-alive" mechanism


Did you read the link you shared?

19.7.1 Compatibility with HTTP/1.0 Persistent Connections

   Some clients and servers may wish to be compatible with some previous
   implementations of persistent connections in HTTP/1.0 clients and
   servers. Persistent connections in HTTP/1.0 must be explicitly
   negotiated as they are not the default behavior. HTTP/1.0
   experimental implementations of persistent connections are faulty,
   and the new facilities in HTTP/1.1 are designed to rectify these
   problems. The problem was that some existing 1.0 clients may be
   sending Keep-Alive to a proxy server that doesn't understand
   Connection, which would then erroneously forward it to the next
   inbound server, which would establish the Keep-Alive connection and
   result in a hung HTTP/1.0 proxy waiting for the close on the
   response. The result is that HTTP/1.0 clients must be prevented from
   using Keep-Alive when talking to proxies.


The author assumes serving documents (i.e. compound data) is not RESTful and a "hack".

In the original Fielding paper, REST is explicitly defined as an architecture for "large-grained resources" aka "documents". So this "hack" the author perceives is inherent to REST.

If your API is small-grained (like most HTTP/web/JSON APIs are), then Fielding explicitly states you shouldn't be using REST.

Quite interestingly and not well-known to many it seems, HTTP/1.1 had many HTTP/2-like proposals like MULTIHEAD and MULTIGET methods. Fielding rejected them on the basis they're not RESTful.

The current praise of HTTP/2 as a major win for REST APIs shows how differently "REST" is understood by its proponents today compared to its original meaning. If doing REST today is about doing the opposite of what it was intended to do, it also raises the question why do we believe we get the same benefits REST did for its original definition? A quick read shows we don't, but the cultural ingraining in favor of "believing" is huge.

TLDR; Nothing to see here, keep doing what works.

P.S.: Server push has been deprecated, it's basically dead.


"RESTful" tends to be used as though it means "good" these days, as though the only good APIs are RESTful. I actually don't think RPC is a bad approach if it suits your problem domain, but designing an RPC API when you think you're not is... probably a bad thing.

REST as an architecture has a lot more in common with how we users traverse the web than how we imagine our machines to query an API. We go from page to page and interpret the content on each page to decide which link to follow next. The HTML media type is understood by our browsers, so we're presented with a consistent way of traversing, submitting forms, etc. that behaves consistently across any site that provides an HTML resource. And a website can update its pages as much as it wants, and as long as it's still providing HTML, a user can learn to navigate it again.

Of course, that genericity and reliance on human learning is exactly what makes HTML alone not a good media type for machine-to-machine REST APIs, but that's why media types are (supposed to be) a cornerstone of REST: they describe the schematic structure of a general kind of resource, specifying how such resources may relate to other resources and what other kinds of data they might contain, but leave it up to the individual resources to actually make use of those facilities (and up to the client to reason against those facilities).

But try finding a "RESTful" API that actually does that. Most of the ones I've seen actually use a bank of statically-known URLs that report a content-type of JSON whose actual fields are statically-known by separate specification. It doesn't really matter whether you're using HTTP or not, that's just RPC.


The whole "REST is good and everything else is dumb" is something I've tried to help people get away from for about a decade. These days it's GraphQL is good and everything else is dumb. See some of the comments in here.

> I wish anything built on REST would die. Conflation of the envelope and the payload is idiotic and adds only pain, no value.

Anyway, a reasoned conversation about where REST can be useful even today: https://apisyouwonthate.com/blog/rest-and-hypermedia-in-2019

And a technical comparison for when people need it: https://apisyouwonthate.com/blog/understanding-rpc-rest-and-...

And when those technical differences can come in useful or just be annoying: https://apisyouwonthate.com/blog/picking-the-right-api-parad...

Loooooots of content on all this. :)


Can you provide a link to the MULTIGET or MULTIHEAD proposals?

I'm very interested in getting GraphQL features into http and wasn't aware of these prior proposals. A quick web search didn't turn up anything for me on them either. Thank you!


Oh, I've discovered them — they were actually called MGET and MHEAD, and are mentioned here: https://www.ics.uci.edu/~fielding/pubs/dissertation/evaluati...


> In the original Fielding paper, REST is explicitly defined as an architecture for "large-grained resources" aka "documents". So this "hack" the author perceives is inherent to REST. If your API is small-grained (like most HTTP/web/JSON APIs are), then you shouldn't be using REST in the first place

This reminds me of the time when people took a format meant for sprinkling some metadata here and there on a piece of a large document, and started using it primarily for writing "documents" where markup/data ratio is > 2.

I'm of course talking about XML here.


If you're not using the full XML ecosystem then yes, it can be overly verbose for just a simple document, especially if the person who defined the format went all in on "XML-ising" it - the worst and most common offender being using elements to define lists of key-value pairs (especially if both have an element wrapped in another element!) instead of using attributes, followed by not specifying a default namespace so everything has "xml:" in front of it making it hard to work out what the hell the thing actually is as well as pointlessly inflating the file size.

When you're dealing with large amounts of structured data of different kinds that you want to combine in many different ways there's not really anything that comes close to the combination of XML, XPath, schemas, XSLT and XQuery. But if you're not something like the huge medical publisher I worked for then you definitely don't need all that.


I agree. I didn't mention this in my original comment, but the follow-up to the story is: the industry eventually moved on to leaner formats like JSON, but in the process, threw away all that made XML very useful over the years - like schemas, for example. Arguably, this is a step back.


I do maintain a couple of JSON schemas and they're a bit clunky due to the JSON syntax (although they're nicer in YAML which my validator can use) but the newer versions of the spec do allow you do specify complex enough rules to cover most cases. But an equivalent to XSLT doesn't make a huge amount of sense for JSON.

I've got an XSLT stylesheet I wrote you can add to an HTML page via the xml-stylesheet directive that turns it into a pretty-printed display of its own markup, complete with syntax highlighting. Pointless but neat that it's possible :)


The current REST practices make SOAP look like a marvel of engineering.

You can tell many of the current "gurus" have no idea what came before (so they reinvented it poorly).


Oh! This explains so much, particularly why I've always felt like most REST APIs aren't really... REST.

Development teams go "ok, we need to design a REST API", and, due to the inherent architectural characteristics of REST (large-grained) clashing with their own needs (small-grained) what they end up with is something more like some Frankenstein-esque REST-RPC monster.


If you make your quotes small enough you can make them mean anything, but I invite you to go take a look at the dissertation. "large-grained resources" does not mean "compound documents", the REST dissertation has no comment on compound documents or anything that resembles the concept, which came along later. It doesn't forbid them or allow them, but many of the concepts of REST suggest otherwise.

Beyond whether its RESTful API or not (grey area) it adds headaches, and is rather unnecessary with good API design anyway, which is what this article was about.

More importantly, compound documents mess with the "cacheability" of resources. A resource cannot declare its own cacheability (which REST suggests) through the uniform interface when its munged into a mismatch of other data. A foo and a bar and a baz are now all cached in together under the same headers with the same /foo?include=bar,baz identifer, meaning that if a bar is likely to change often you have to request the whole thing again. This is one of many reasons compound documents are a pain in the ass, but there are plenty more.

Fastly wrote about all this: https://www.fastly.com/blog/optimise-api-cache-improved-perf...

> The current praise of HTTP/2 as a major win for REST APIs shows how differently "REST" is understood by its proponents today compared to its original meaning. If doing REST today is about doing the opposite of what it was intended to do, it also raises the question why do we believe we get the same benefits REST did for its original definition? A quick read shows we don't, but the cultural ingraining in favor of "believing" is huge.

This whole paragraph makes no sense. I have been making APIs since ~2008 so let's not act like I'm brand new at this.

The point I was making here is that in the past people have moaned about REST because "making lots of requests is slow", which is a common comment from people who generally build their APIs poorly not taking into consideration what the consumers would be doing and just flopped out a very normalized database and forced clients to construct their own data models from that. It's also a concern from people who havent got the first clue what HATEOAS means or how it can help abstract state from multiple clients up into the backend. They just see it as "having to make more requests".

Now that the fear of multiple requests is subsiding, the exact same concepts that made REST beneficial for many APIs in the HTTP/1.x past exist now, they're just quicker in HTTP/2. And they're quicker in HTTP/3. REST and HTTP just get quicker and more useful over time.

Anyway, you sound like you might enjoy this article: https://apisyouwonthate.com/blog/rest-and-hypermedia-in-2019


The forum link on the site is broken. Assume everything is on their Slack channel now.

The link:

https://forum.apisyouwonthate.com/


Compound documents are not only for reducing network latency. It also about giving your clients a nice single point of entry and not having them call 5 endpoints to get what they need.


It sounds nice at first, but if you have 5 completely different resources then why would you want to squish them into one? This taints highly cacheable data with frequently changing data, and slows down everything all at the same time.

Also when 5 becomes 8, 9, 10.... entire APIs come grinding to a halt because people are trying to download the entire database in one single request instead of just making a few calls.


Maybe I'm a bit stupid but I don't understand this premise of this article.

For example,

> Invoices don't need payment status, or an array of order items, so we don't need to worry about trimming down the response at the field level, they can just be their own related resources, discoverable with hypermedia controls.

To me, this misses the mark in two ways.

First, invoices might need payment status, if that's what your UI is trying to render. So, you can certainly have a payment status endpoint, but that's going to add some milliseconds to your UI response times, and if you also have separate API calls for invoice line items, fulfilment status, associated data... well you do have a lot of duplicate I/O going on, even with HTTP/2 and compression, and the API is not really ergonomic from the perspective of the user of the service. There's a lot of client-side LOC in play to make all these calls, and a lot of server-side dependencies end up being exposed by the structure of the APIs.

Second, including the payment status for an invoice is useful and almost (but not always) something that an API consumer is going to request alongside the invoice data. So for the consumer's convenience, you'd typically want to include it in the invoice representation. The API is going to be better off for having it.

In this case, however, we have the problem that obtaining the payment status (or other seemingly simple data) may in fact be expensive. Depending on the architecture of the system, at a minimum it's probably another database query, but the payment status might even be in a completely separate service.

Ultimately, the cost of excess round trips is really paid for by the end-user, but the cost of loading unnecessary/unwanted data is paid for by the service provider. GraphQL, and presumably other sparse fieldset APIs, provide a way to optimise both sides of the API.

This is where GraphQL makes perfect sense to me. It lets you build a discoverable data model that considers the logical structure of the API and the consumer's ergonomics, but because the caller only requests the fields they need, and because GraphQL fields are fetched independently, you don't have to compute those fields unless you need to. The result is super fast APIs that are easy to discover, consume and debug, and that use the optimal level of resources at both ends of the connection, a solution which IMO is infeasible with pure REST APIs distributed over many servers.


I covered all of that in a previous article and many more since. https://apisyouwonthate.com/blog/graphql-vs-rest-caching

Basically, trimming a few bits off of a request is not overall quicker than helping clients not need to make as many requests by designing an API well enough that resources can live on their own and declare their own cachability.

Designing your API resources so that primary data can be fetched and displayed before you start mucking around with secondary and tertiary data is also important. When you talk about being slower for the user, is it actually slower for a real human doing real things on the site. For example, I've seen GraphQL queries loading a social media feed, and list of friends for a little box on the side which didnt matter, and a list of comments on posts that havent even been expanded yet so now user could see it, and querying to see if there is any availability in conference rooms even if theyve not shown any interest in booking a conference room. The clients wanted to avoid making multiple calls because ooooh thats bad, but the whole page was just a blank white screen until all that pointless data came back. Querying all of those resources seperately over the same HTTP/2 connection and letting the UI progressively enhance would absolutely be quicker than mushing it all into a single giant HTTP request but that's what everyone does. All the time. It's insane.

Again, Fastly wrote about all of this very well. This article is one in a series which doesn't stand as well on its own.

https://www.fastly.com/blog/optimise-api-cache-improved-perf...


I am actually a tad concerned that this article made it past 100 upvotes. It was my own treshold for giving an entry some attention, and I think it is time to give it a bump. I used to regard HN as collaborative filter for a wide stream of tech news, announces, tutorials etc, but recently an average quality of that filtered data became a bit disappointing. Or maybe it's just my own standard got higher?


I would have liked the author to have acknowledged dataloader in the context of graphql.


Dataloader is an implementation quirk of a particular library, not a protocol quirk of GraphQL as a query format.


Graphql is much nicer to use than the suggested solution to do one billion http requests for the sake of it.


GraphQL, OData, and JSON:API some of many compound document implementations you can use to mush multiple resources into a single request, this article was about how doing that is pointless and sometimes detrimental.


4 years later and Id argue graphql is the clear market winner. Whether or not you really need it is debatable but its fashionable. Schema driven development and types have also been adopted along side that system so they sort of fit well together, too.


I have almost never encountered GraphQL in production, including when inspecting other sites. I think it's still a pretty small niche and mostly used on newer projects.


I was going to comment something similar to this. We integrate with a lot of APIs every day and graphql we have never encountered. It seems, for now, to be a HN distortion field that it is 'a clear market winner'? It seems not only to be used on newer projects but at a specific type of startup projects. Looking at HN launches which have an API recently, it seems hardly used at all yet.

The problem being that not many people seem to know how to implement it server side, while REST is trivial.


> while REST is trivial.

I'm not convinced of this -- or at least, we might use different definitions of "REST".

The guy who created the concept of REST regularly (or used to regularly) call out common problems with "REST" APIs that make them more like RPC APIs that happened to be built on top of HTTP. For instance, [0].

Now, just because someone created a thing doesn't mean they had it right from the get-go. (For instance, the guy who named "gif" clearly pronounces it wrong.) But I've become convinced by Roy's points about what REST ought to be, and if "REST" is going to be meaningfully distinguished from "RPC", it's probably worth understanding his position.

[0] https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypert...


I see your point and yes, you are right. I probably would have to say that 'what people gobble together and call REST is easy to implement' and sidestep the problem that it has a lot of issues. Or maybe just that it is far easier than graphql to bolt on server-side. But yes, I agree with your comment.


Yes, sorry to pick on you specifically for that ;)

In my admittedly limited experience, GraphQL is easier to get right than true REST, but obviously somewhat harder than a slapped-togther RPC API. I also like GraphQL better because if your domain fits it, it's really easy to use a GraphQL schema as a limited kind of domain model in its own right. And you can factor that schema (as well as describe proposed patches to it) with `extend type`, not unlike C#'s `partial class`.


I am quite enthusiastic about grapql, but the teams at my clients just stare at me like I am crazy and then go back to work. Basically everyone would rather do create /api/userswithgroupsandaclsandinvoices next to /api/users than look for other options. It's just so quick & easy to do that instead of look at other tech. I guess in companies beyond a 2 people startup team, the persons having to use the API and the persons creating it are different groups and they both are doing what is easy for them and their team. I think we would need to see a lot more server implementation and benefit tutorials for grapql to fix that issue.

In the case of most of our partners and clients for instance, the API users are other companies in the same vertical; not only do the API teams not care a lot about the usage as long as it works; spending time doing something 'fashionable in the cutting edge dev world' might be nice, but no-one in their vertical will use it. They will simply ask for the 'normal API' instead.


I don't know much about GraphQL, but my instinctive reaction to it is that it seems like it has a lot of hidden consequences that I would not be able to predict in advance. For example, from what I've seen it seems like it would be easy to write queries with exponentially large responses, and that just seems dangerous to expose in an API.


It's definitely hard to argue against something so easy, right? At the same time, it's often really hard for people to grasp that a solution now might have repercussions later -- and even if they do, maybe they won't be around to worry about the repercussions anyway.

And if there won't be repercussions -- maybe the product is short-lived, maybe they're okay with forcing clients to upgrade every X months, maybe they rewrite the backend software regularly so cruft can't accumulate so easily -- are they wrong?

GraphQL can't tell you what your problems are. I agree that there could be more resources out there, but as software engineers, we have to wrangle with the specific problem domain we're being asked to solve, and decide what the core issues are and how to tackle them. Nobody outside your team can do that for you (and I count consultants as being on your team, even if temporarily).


> And if there won't be repercussions -- maybe the product is short-lived

Unfortunately the API's I work with are long-lived; decades. Many (but not close to most luckily) integrations are SOAP for instance. With API versioning and 'hidden' APIs (API's which are not in their normal Swagger or docs, but do exist to fix), issues like returning too much or too little is resolved, and it's fast & easy.


REST is trivial only when it's RPC by another name.


Same for me. I will add to this that probably very few know how to implement GraphQL on the server-side *efficiently*, or, put differently, most have a gut feeling about how hard to manage it can become.

While frontend implementations look good, GraphQL sure looks like an unsolved problem on the server to me.


I don't use it only because people at other companies demand REST.


I guess clear market winner depends on what one defines as market.

Anecdotally though, I have been working with medium sized startups in NYC that are heavily API driven for the last several years, and I haven't seen graphQL in production once. Not at my companies, nor in any external API we have interfaced with.

I will even go a step farther and day that I cannot recall a single time that another of the several dozens of devs or managers I have worked with has even mentioned the idea of using it.

I can only assume the market OP is referring to is a very specific one. I could make a guess or two, but wouldn't want to ruin the reader's enjoyment from doing the same.


Counter-anecdote: the last two places I've worked at have adopted GraphQL in production, and are happier for it.


I didn't intend to imply that GraphQL is better or worse than REST-ish APIs. I just haven't seen it catch on anywhere outside of Facebook.

I have integrated many dozens of APIs into backends by now, and never have I even had an option to use GraphQL if I wanted to.


FWIW, my team has adopted GraphQL because it fits our domain needs better in a few ways. Our product is org-internal, so that might play into the choice a little bit.


I wish anything built on REST would die. Conflation of the envelope and the payload is idiotic and adds only pain, no value.


REST is more or less a description of the architectural design principles that made the web a success. You wish for the web to die?


Fielding has no problem recognizing the web needs one architectural style, and small-grained data APIs need another. The web doesn't need to "die". Our infinite ignorance on what REST is and what it should be used for has to die. Fielding hasn't mentioned the word "API" once in his paper. This entire REST API movement is a paradox that mocks everything he explicitly warned us about in his dissertation.


I've gotten value from HTTP responses in the 300s, 400s, and 500s being handled appropriately by various tools without having to write special RPC logic for those cases. What am I missing?


> I've gotten value from HTTP responses in the 300s, 400s, and 500s being handled appropriately by various tools without having to write special RPC logic for those cases. What am I missing?

What exactly is behind this statement?

What tools do you have in mind, and what do they do with 400s and 500s? Other than Chrome DevTools coloring the response in red automatically, a big win. /s

I've also never seen an API redirect and force a pointless second (and third etc.) roundtrip for the client to get the same exact content.

Just because (some) of these codes mean something for a web page and a browser, doesn't mean they're automatically meaningful for a real-world API. That's the critical distinctions, which REST fans refuse to acknowledge.


Middleware comes to mind (eg caches, proxies, api gateways).


HTTP and REST are never reliably supported by clients. For example, many JavaScript clients will throw exceptions for 4xx and 5xx errors, even though handling 4xx errors in the client application is very reasonable.

Other clients only treat 5xx as a throwable exception, and some don't throw unless the request fails to hit the HTTP server.

Because of these issues, your best bet is to just wrap your HTTP API in a native client library. You certainly can't target a generic HTTP or REST wrapper.


That's a reflection on a small number of Yet Another Not Invented Here clients, as opposed to the protocol and paradigm


Yes, I agree it is not a reflection of the protocols. It doesn't matter either way -- if you have a standard that no one fully implements, your standard is not practically meaningful.


I think partially implemented standards are very useful! You can partially implement in a way that provides escape hatches for users, or you can lock them in to your assumption of the right behaviour.

That said, I think there are very many http clients that implement enough of the standards to me incredibly rich and in line with the spirit of the protocol. The web for humans and machines is based on http. It can improve, but the standard has quite sufficient support to be called practically meaningful


That a 404, 301, and 500 being generated by the API vs the web server are very different events and it’s hard to think of where “various tools” handling them the same is the right choice? What examples do you have where it’s the right choice?


With application servers acting as the authoritative state of a user's current phonecall status, the api client wants a websocket connection to the shard with that user's state. It connects to one and is 302'd to the appropriate shard. It how has a websocket connection directly to the authoritative source to get notified of any state changes.

I forget exactly what the scenario was but the request was not being sent with credentials so a 401 was returned, which immediately prompted a retry with the credentials. I'd probably agree that this is covering up an issue that should be fixed.


How is this a REST API rather than just a regular API being served over HTTP?


Curiously the websocket spec says the server may send 30x code during handshake, but the client is "not required to follow it".

So in this case you're relying on a specific client's decision more than you're relying on universal interface.


That's a constructive comment based on a well rounded understanding of the various architectures and paradigms around. You sound well balanced and like you're a pleasure to work with.


I wish rebuilding RPC infrastructure every couple of years would die, I already lost count of how many times since DCE RPC was cool.


Unlike everyone improvising on "what it means to be REST", no one is shoving RPC down your throat.


They surely are, when the libraries I have to plug into decide it is time to reboot their eco-system and offer only the new way as the path forward.


And what libraries are those...?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: