GraphQL was created at Facebook in 2012 for its mobile applications, published as an open specification in 2015 and is maintained by the GraphQL Foundation; the current specification edition is dated October 2021. The server publishes a schema: types with named fields, each field with its own type, and three kinds of operation a client may send. A query reads, a mutation writes and then reads, and a subscription keeps a connection open so that the server can push data when an event happens. Because the schema is itself queryable, a client can ask the server what it offers, which is how editors autocomplete queries and how documentation stays in step with the code.
The practical difference from a REST API is who decides the shape of the response. REST fixes it per endpoint: a request for user 42 returns the user as the server designed it, and a screen that needs the user plus the last five orders makes two calls or asks for a bespoke endpoint. In GraphQL the client writes the shape, user 42 with the name and the totals of the last five orders, and the server assembles it by running a resolver function for each requested field. One request, no over-fetching, no under-fetching, and no new endpoint when a screen changes.
| Concern | REST | GraphQL |
|---|---|---|
| Response shape | Fixed by the server per endpoint | Chosen by the client per query |
| Round trips for a composite screen | Several, or a custom endpoint | One |
| HTTP caching | Works by URL out of the box | Mostly POST to one URL; caching moves into the client or a gateway |
| Cost control | Per endpoint, easy to reason about | Per query; needs depth and complexity limits |
| Tooling | Any HTTP client | Schema-aware clients, introspection, code generation |
The costs follow from the same design. Resolvers that fetch one row at a time turn a routine query for a hundred users and their orders into a hundred and one database calls, the N+1 problem, which batching libraries exist to solve. Every request is a POST to one URL, so the HTTP cache that a REST interface gets for free has to be rebuilt in the client or at a gateway, and caching strategy becomes a design task. Authorisation applies per field rather than per route. None of this is a reason to avoid GraphQL; it is the engineering a team takes on in exchange for client-driven queries, and it is why the style pays off in back-end and API work that serves many clients and rarely in a single-page site with one consumer.
