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]
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.
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.
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.
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.