What is GraphQL?
GraphQL explained: queries vs REST, the schema definition language, resolvers, and why over-fetching is the problem it was built to solve.
GraphQL is a query language and server-side runtime for APIs, created at Facebook in 2012 and open-sourced in 2015. Instead of a fixed set of endpoints that each return a fixed shape of data, a GraphQL API exposes one endpoint and lets the client describe exactly which fields it wants, across however many related types, in a single request.
It's not a database and doesn't replace one. A GraphQL server's resolvers fetch data from whatever actually stores it, SQL, a document store, a REST API, another service, GraphQL just defines the contract for asking for it and the shape of what comes back.
The problem it solves: over-fetching and under-fetching
A REST endpoint like /api/users/42 returns whatever shape the server decided on, so a mobile screen that only needs a name and an avatar URL still downloads the full user object (over-fetching), and a screen needing a user's posts and their comments needs multiple round trips or a bespoke endpoint built just for that screen (under-fetching).
query GetUserWithPosts($id: ID!) {
user(id: $id) {
name
avatarUrl
posts(first: 5) {
title
publishedAt
}
}
} One request, exactly the fields asked for, however deep the nesting. The tradeoff moves complexity to the server: a naive resolver for posts that runs one query per user is the classic N+1 problem, which is why production GraphQL servers lean on request-scoped batching (DataLoader and similar) to collapse those into a single query.
Queries, mutations, and subscriptions
| Purpose | Side effects | |
|---|---|---|
| Query | Read data | None expected |
| Mutation | Create, update, delete | Yes, and the spec runs them sequentially per request |
| Subscription | Real-time updates | Long-lived connection, typically WebSockets |
Mutations running sequentially (not in parallel, unlike queries in the same request) matters when one mutation's result affects the next, GraphQL guarantees that ordering so you don't have to work around a race.
SDL: the schema, written by the server
The Schema Definition Language is how a GraphQL API declares its own shape, every type, field, and argument the server exposes:
type User {
id: ID!
name: String!
posts(first: Int): [Post!]!
}
type Post {
title: String!
publishedAt: String
} A trailing ! marks a field non-nullable. SDL and queries share the same underlying grammar, which is why a single parser, graphql-js, the reference JavaScript implementation, handles both. The GraphQL Formatter on this site is built on that same parser: paste a minified query from a network tab, or SDL from a schema file, and it re-prints either with consistent indentation.
Frequently asked questions
No, it's a query language and runtime for APIs, not a storage engine. A GraphQL server's resolvers typically fetch data from whatever actually stores it: a SQL database, a document store, a REST API, or another GraphQL service, and GraphQL just defines the contract for asking for it.
This is a common first misconception because the query syntax looks like it's querying a database directly. In practice a GraphQL layer is usually sitting in front of infrastructure that already exists.