9 min
  • APIs
  • HTTP

REST, and what GraphQL changes

An API is ordinary HTTP with the audience changed. Because the caller is code rather than a person, the parts that matter most are the ones a human would forgive: exact status codes, stable shapes, and errors that say what to do next.

REST's organising rule is that the URL names a thing and the method is the only verb.

http
GET    /posts        list themPOST   /posts        create one; the server names itGET    /posts/7      read that onePUT    /posts/7      replace it entirelyPATCH  /posts/7      change part of itDELETE /posts/7      remove it

Putting the verb in the method rather than the path is what lets every cache and proxy between the client and the server reason about a request without understanding the application at all.

Loading the API Visualizer simulation…

Idempotency is about the state, not the status

The run above sends POST and PUT twice each, because this is the property everything else depends on. Two identical POSTs create two resources; two identical PUTs leave one. That is why a client library may safely retry a PUT after a timeout and may not retry a POST.

DELETE answering 404 the second time is still idempotent. Idempotency is a claim about the state left behind, not about the response.

StatusSaysCarries
201A resource now existsLocation, naming it
202Accepted, not doneLocation, pointing at progress
204Done, and there is nothing to sayNo body at all — not even {}
405Wrong method for a real resourceAllow, listing what works
422The JSON parsed and made no senseAn explanation
Check yourself
A client sends POST /orders and the connection times out with no response. May it safely retry?

What GraphQL trades away

GraphQL takes the opposite position: one endpoint, one POST, and the client describes the shape of the response it wants. A screen needing a user, their posts, and each post's comment count is one request instead of several, and returns no field the client did not ask for.

Loading the API Visualizer simulation…

What is given up is everything that came from having a method and a URL. HTTP caching does not apply to a POST to one endpoint. Per-resource authorisation has to be reimplemented inside the resolver layer. And the cost of a request is no longer obvious before it runs, because the client wrote the query.

Predict what happens next
A GraphQL API is behind a CDN. How much of it can the CDN cache?

Key takeaways

  • A web API is ordinary HTTP with a program as the client, so exact status codes and stable shapes matter more than they do for a person.
  • REST puts the noun in the URL and the verb in the method, which lets intermediaries reason about requests without understanding the application.
  • Idempotency describes the state left behind, not the response — a second DELETE returning 404 is still idempotent.
  • A timed-out POST cannot be safely retried, because a lost response and a lost request look identical from the client.
  • GraphQL buys exact response shapes and one round trip, and gives up HTTP caching, per-resource authorisation, and predictable cost.

Take it further