GraphQL

What is GraphQL?

GraphQL is a query language and runtime for APIs, originally developed by Facebook in 2012 and open-sourced in 2015. Unlike REST, where each endpoint returns a fixed data structure, GraphQL exposes a single endpoint and lets the client specify exactly which fields it needs. The server responds with precisely that data -- nothing more, nothing less. The API is defined by a strongly typed schema that describes every available type, field, and relationship, serving as both documentation and contract.

A GraphQL query looks like a JSON template of the desired response. The client writes a query describing the shape of the data it needs, and the server returns data in that exact shape. This declarative approach eliminates the guesswork that comes with navigating dozens of REST endpoints.

Why does it matter?

REST APIs suffer from two persistent problems: over-fetching and under-fetching. Over-fetching occurs when an endpoint returns more data than the client needs -- a mobile app requesting a user profile receives the full user object when it only needs the name and avatar. Under-fetching occurs when a single view requires data from multiple endpoints -- displaying a dashboard might require separate calls to /users, /orders, /analytics, and /notifications, each adding latency.

GraphQL eliminates both problems. The client requests exactly the fields it needs, and nested relationships are resolved in a single request. A dashboard that previously required four REST calls can be served by one GraphQL query. For mobile applications on slow connections, this reduction in request count and payload size translates directly into faster load times and lower data consumption.

The typed schema is equally valuable. Every query is validated against the schema before execution. If a client requests a field that does not exist, the error is caught immediately -- not at runtime in production. Frontend and backend teams can develop against the schema in parallel. TypeScript code generators produce type-safe client code directly from the schema, eliminating an entire class of runtime errors. The schema also serves as living documentation that is always accurate, unlike manually maintained API docs that drift from reality.

For organizations with multiple client applications -- web, mobile, internal tools -- GraphQL provides a unified data layer. Each client queries the same schema but requests different fields based on its needs. The mobile app fetches a minimal dataset; the admin dashboard fetches comprehensive details. No backend changes are required to serve different clients, reducing the coordination overhead between teams.

GraphQL in practice

A GraphQL API is built around three core concepts: queries (reading data), mutations (writing data), and subscriptions (real-time updates via WebSockets). The schema defines the available operations and the types they return.

A typical implementation uses a Node.js server with Apollo Server or Mercurius. The schema is defined using SDL (Schema Definition Language), and resolvers -- functions that fetch the actual data -- are mapped to each field. For example, a Product type with a reviews field has a resolver that fetches reviews from the database only when that field is requested. This lazy resolution prevents unnecessary database queries.

Consider an e-commerce application. A product listing page needs product names, prices, and thumbnail images. The product detail page needs descriptions, specifications, all images, reviews, and related products. With REST, either you create separate endpoints for each view, or the listing page receives data it does not need. With GraphQL, each page sends a query requesting exactly its fields:

# Listing page
query { products { name price thumbnail } }

# Detail page
query { product(id: "123") { name price description images reviews { rating text } related { name price } } }

The same backend serves both queries without any endpoint duplication.

Federation extends GraphQL to microservices architectures. Each service owns its portion of the schema -- the product service defines Product, the review service defines Review -- and a gateway composes them into a unified schema. Clients interact with a single GraphQL endpoint without knowing how the backend is distributed.

Performance considerations include the N+1 query problem, where nested fields trigger excessive database queries. DataLoader -- a batching utility -- solves this by collecting field requests and executing them in a single batch query. Caching is more nuanced than with REST because responses vary based on the query. Persisted queries, response caching, and CDN-level caching strategies address this effectively.

Related concepts

We respect your privacy

This website uses cookies for essential functions and optionally for analytics and marketing. Privacy Policy