Conceptly
← All Concepts
πŸ“Š

GraphQL

APIAn API query language through which clients precisely request the data they need

GraphQL is an API query language and runtime open-sourced by Facebook in 2015. When a client specifies the fields it needs using query syntax, the server returns a response in exactly that structure. All data requests are handled through a single endpoint (/graphql), and a schema defines the types and relationships within the API. Data retrieval is expressed with query, modification with mutation, and real-time subscriptions with subscription. Because the client controls the shape of the response, it structurally reduces both over-fetching and under-fetching.

β–ΆArchitecture Diagram

πŸ”— Relationship

Dashed line animations indicate the flow direction of data or requests

Why do you need it?

Developing a frontend with a REST API creates recurring friction. A user profile page needs only a name and avatar, but the /users/123 response comes with dozens of fields including join date, settings, and activity history. Conversely, to show a user's recent posts and follower count on the same screen requires three calls: /users/123, /users/123/posts, and /users/123/followers. A mobile app needs far less data than a desktop app, but using the same endpoint brings useless bytes over the network. Each time the frontend team says 'this screen needs this field combination', the backend must either create a new endpoint or add query parameters to an existing one. This pattern repeated means more and more APIs, and the deployment cycles of both teams become entangled.

Why did this approach emerge?

When Facebook converted its mobile app to native in 2012, this problem became severe. Rendering a single News Feed item required dozens of types of data -- user information, posts, comments, likes, and photos -- and calling REST endpoints one by one exploded the number of requests, while responses contained large numbers of fields unused on the screen. In a mobile environment, this inefficiency translated directly into slow loading and wasted data charges. GraphQL, which Facebook had been developing internally since 2012, was structured so that clients described the shape of the data they needed and the server responded in exactly that shape. After being open-sourced in 2015, it was adopted by GitHub, Shopify, Airbnb, and others, and spread rapidly among services with complex frontend requirements.

How does it work inside?

In GraphQL, an API call operates in three stages. First, schema definition. On the server side, the types that exist, the fields each type has, and the relationships between types are declared using schema language. For example, the User type is defined as having name, email, and posts fields, where posts is an array of the Post type. This schema serves as the contract for the API. Second, query writing. The client writes a query by listing the needed fields inside curly braces. Sending { user(id: 123) { name, posts { title } } } is a request for only the name and post titles. The mutation keyword is used for data changes and subscription for receiving real-time events, both using the same syntactic structure. Third, resolver execution. The server executes the resolver function mapped to each field in the query. The resolver for the user field fetches the user from the database, and the resolver for the posts field fetches that user's posts. Resolvers can fetch data from a database, another API, a cache, or any other source. Once execution is complete, a JSON response is assembled in exactly the structure the client requested.

In Code

Schema and query share the same contract

type User {
  id: ID!
  name: String!
}

query {
  user(id: 123) {
    id
    name
  }
}

Read the type definition and the client query together to see what the server guarantees and what the client asks for.

Resolvers gather data field by field

const resolvers = {
  Query: {
    user: (_: unknown, { id }: { id: string }) => db.users.find(id),
  },
};

GraphQL still fetches real data behind one endpoint. The key is reading the pair of query and resolver, not the URL alone.

What is it often confused with?

GraphQL and REST are both API layers for exchanging data between client and server. But the locus of control differs. In REST, the server determines the endpoints and response structure, and the client uses what it receives. In GraphQL, the client specifies the desired data structure in a query, and the server responds accordingly. REST is more appropriate when the resource structure is simple and stable, when HTTP caching should be actively leveraged, and when a publicly exposed API needs to be kept as simple as possible. GraphQL is more appropriate when the data combination needed varies significantly per screen, when multiple resources must be fetched in a single request, and when the frontend needs to move independently without being tied to backend deployments. GraphQL has its limitations. With a single endpoint, HTTP-level caching is not as straightforward as with REST, and without policies to limit query complexity, server load can grow in unpredictable ways. Binary handling such as file uploads also requires additional conventions.

When should you use it?

GraphQL delivers its greatest benefit in services where frontend data requirements are complex and change frequently. For cases like social feeds, dashboards, and e-commerce product detail pages where multiple types of data must be assembled on a single screen, a single query can fetch exactly the data needed, reducing network round trips and unnecessary data transfer. It is also useful when multiple different clients -- web, mobile, watch apps -- share the same backend. Each client sends the query that fits its own screen, eliminating the need to create dedicated endpoints per client. In microservice environments, a federation pattern can be applied that merges the schemas of multiple services into one. The frontend queries a single graph, and the gateway distributes requests to the service responsible for each field. There are also cautions when evaluating adoption. Initial investment in schema design and resolver optimization (such as DataLoader to prevent the N+1 problem) is required, and operating without query complexity limits can allow a single query to impose excessive load on the server. For simple CRUD APIs, REST builds faster and carries less operational overhead.

Complex frontends -- dashboards and social feeds that need to assemble multiple resources on a single screenMultiple client types -- when web, mobile, and watch apps each need a different data structureRapid prototyping -- when the frontend can create a new screen just by changing its query without any backend changesMicroservice aggregation -- exposing data from multiple services combined into a single graph