Cloud Parts

GraphQL

A query language and runtime for APIs: the server publishes a typed schema, and each client asks one endpoint for exactly the fields it needs.

What it is
Web APIs
Type
Open source
Made by
GraphQL Foundation (Linux Foundation), created at Facebook
License
Specification: Open Web Foundation Agreement 1.0 since September 2017; GraphQL.js reference implementation: MIT since September 2017 (BSD plus a patent grant before)
Facts checked
9 October 2026

What it is

A GraphQL service publishes a schema written in GraphQL’s type language: object types with typed fields, such as an Order with a status and a customer, plus root types listing the entry points for queries (reads), mutations (writes) and subscriptions (streams of events). Clients send a document to one endpoint, conventionally POST /graphql with a JSON body holding the query and its variables. The server parses the document and validates it against the schema before running anything, then executes it. Every field is backed by a resolver, a function that gets its parent object and the field’s arguments and returns a value from a database, another service or memory. Query fields may resolve in parallel; the top-level fields of a mutation run one after another. The response is JSON with the data under data, shaped exactly like the query, and any problems under errors, so one response can carry partial data and errors together. The schema can itself be queried (introspection), which powers editors such as GraphiQL, code generators and typed clients.

The specification defines the language, type system, validation and execution, and deliberately leaves out transport and storage. HTTP with JSON is the usual pairing, described by a separate GraphQL over HTTP specification that is still a draft; subscriptions usually run over WebSockets or server-sent events. GraphQL.js is the reference implementation (v17 shipped in June 2026), and there are servers for most languages, such as Apollo Server, GraphQL Yoga, graphql-java and Strawberry, plus engines that generate a schema from a database. The GraphQL Foundation, part of the Linux Foundation, publishes the spec in dated editions; the September 2025 edition, the first since October 2021, added OneOf input objects and schema coordinates. Using GraphQL costs nothing; managed services such as AWS AppSync charge per operation.

Why teams pick it

  • Each client asks for exactly the fields it needs, across related objects, in one request: fewer round trips and smaller payloads on mobile networks
  • A typed schema: queries are validated before they run, and introspection drives GraphiQL, code generation and typed clients
  • Evolves without version numbers: new fields don’t affect existing queries, and old ones are marked @deprecated while they keep working
  • One endpoint over many backends: resolvers can call databases, REST APIs and gRPC services, so a GraphQL layer can unify existing systems
  • Subscriptions use the same schema and query language as reads, for real-time updates

Watch out for

  • HTTP caching is harder: requests are usually POSTs to one URL, which browsers and CDNs don’t cache. You need GET with persisted queries, or client-side caches keyed by globally unique object IDs
  • The N+1 problem: naive resolvers make one backend call per item in a list, so 50 orders can mean 50 customer lookups. Batching with a tool like DataLoader is effectively required
  • Clients write the queries, so a deep or wide one can overload the server. Public APIs need depth limits, cost analysis or rate limits by cost; GitHub charges points per query, 5,000 an hour per user, and requires a page size on every list
  • Errors don’t map to HTTP status codes: a response with partial data comes back as 200 with an errors list, so monitoring by status code misses failures
  • File uploads aren’t in the spec: servers adopt a community multipart convention, and graphql.org recommends uploading through signed URLs instead

Alternatives

What all web apis have in common →

How it fits with other technologies

A GraphQL Yoga server with resolvers and DataLoader batching · ts

// npm install graphql graphql-yoga dataloader pg
import { createServer } from "node:http";
import { createSchema, createYoga } from "graphql-yoga";
import DataLoader from "dataloader";
import pg from "pg";

const db = new pg.Pool(); // connection settings from PGHOST, PGUSER, PGDATABASE...

const typeDefs = /* GraphQL */ `
  type Query {
    order(id: ID!): Order
    recentOrders(first: Int = 20): [Order!]!
  }
  type Order {
    id: ID!
    status: String!
    customer: Customer!
  }
  type Customer {
    id: ID!
    name: String!
  }
`;

const resolvers = {
  Query: {
    order: async (_: unknown, { id }: { id: string }) =>
      (await db.query("SELECT id, status, customer_id FROM orders WHERE id = $1", [id])).rows[0] ?? null,
    recentOrders: async (_: unknown, { first }: { first: number }) =>
      (await db.query("SELECT id, status, customer_id FROM orders ORDER BY created_at DESC LIMIT $1", [Math.min(first, 100)])).rows,
  },
  Order: {
    // Runs once per order; the loader turns 20 calls into one query (no N+1)
    customer: (order: { customer_id: string }, _: unknown, ctx: { customers: DataLoader<string, unknown> }) =>
      ctx.customers.load(order.customer_id),
  },
};

const yoga = createYoga({
  schema: createSchema({ typeDefs, resolvers }),
  // A fresh loader per request, so batches and its cache never mix users
  context: () => ({
    customers: new DataLoader<string, unknown>(async (ids) => {
      const { rows } = await db.query("SELECT id, name FROM customers WHERE id = ANY($1)", [ids]);
      return ids.map((id) => rows.find((row) => row.id === id) ?? null);
    }),
  }),
});

createServer(yoga).listen(4000); // POST http://localhost:4000/graphql

// Client: { recentOrders(first: 20) { id status customer { name } } }

What a server does with a request#

The spec defines each step as an algorithm, so every conforming server, in any language, runs them in this order. Anything that fails before execution is a request error: the response has errors and no data at all.

What happensIf it fails
1. ParseThe document text becomes a syntax tree of operations and fragmentsSyntax error: request error, nothing runs
2. ValidateThe operation is checked against the schema: every field exists on its type, objects get a selection of subfields and leaf fields don’t, fragments don’t form cycles. A server may skip this for a document it has validated before and that hasn’t changed, such as a persisted queryValidation errors: request error, nothing runs
3. Pick the operation and coerce variablesIf the document holds several operations, the client names one. Variable values are converted to their declared typesMissing operation name or a wrong variable type: request error
4. ExecuteResolvers run from the root fields down. Query fields can run in any order, normally in parallel, because they must be free of side effects; the top-level fields of a mutation run one after another. Each value is coerced to its schema type, so an enum stored as a number comes back as its nameExecution error: that field becomes null and the error goes into errors with its path. A null in a non-null field spreads up to the nearest nullable parent
5. RespondA map with data shaped like the query, errors if any were raised, and optional extensions, usually serialized as JSON. A subscription returns a stream of these results, one per eventNothing new: errors raised earlier are already in the response

Introspection: the schema answers questions about itself#

Every GraphQL service can be queried about its own schema, in GraphQL. The meta-field __typename works in any selection set (except at the root of a subscription) and returns the name of the concrete object type, which is how a client tells the members of a union or interface apart. The query root also has two hidden fields: __schema, which lists every type, the root operation types and the directives, and __type(name: "Book"), which describes one type. Introspection types and fields start with two underscores (__Type, __Field, __EnumValue and so on), a prefix your own names may not use.

Everything in a schema can carry a description, which may be written in Markdown, and fields, arguments, input fields and enum values report isDeprecated and a deprecationReason. That is what lets GraphiQL autocomplete queries and show documentation, and lets code generators produce typed clients. graphql.org notes that APIs used only by your own apps rarely need introspection in production, because their queries are fixed at build time, and that disabling it is a common way to shrink the attack surface.

REST, GraphQL and gRPC#

All three run over HTTP, but they put the contract, and the choice of what comes back, in different places.

RESTGraphQLgRPC
ContractOptional, often an OpenAPI documentA schema, required; clients can query itA .proto file, required
EndpointsOne URL per resourceOne, usually /graphqlOne path per method, /package.Service/Method
Who shapes the responseThe server, per endpointThe client, per queryThe server, per message type
EncodingUsually JSONUsually JSON; the spec doesn’t require oneBinary Protobuf by default
HTTP cachingBuilt in: GET with Cache-Control and ETagOnly with GET or persisted queries; otherwise client-side cachesNot used
ErrorsHTTP status codesAn errors list in the body, often with status 200Status code in HTTP/2 trailers
Real-timeNot defined by the styleSubscriptions; the transport is left to the implementationServer, client and bidirectional streaming
From a browserDirectlyDirectlyOnly through gRPC-Web and a proxy

Ways to run a GraphQL API#

You can write resolvers yourself, generate the schema from a database, or rent a managed service. AWS list prices checked October 6, 2026.

GraphQL.js

reference, MIT

The JavaScript reference implementation maintained by the GraphQL Foundation; v17 shipped in June 2026. Many Node servers build on it.

Apollo Server and GraphQL Yoga

Node servers, MIT

Full HTTP servers around GraphQL.js. Other languages have their own, such as graphql-java. In Python, Strawberry, Ariadne and Graphene all run on GraphQL-core, a close Python port of GraphQL.js.

Hasura, PostGraphile, pg_graphql

generated

Build a GraphQL schema from an existing database. pg_graphql runs inside PostgreSQL as an extension and is called through one SQL function, graphql.resolve.

AWS AppSync

managed

Resolvers connect fields to DynamoDB, Lambda, OpenSearch, RDS, EventBridge or HTTP endpoints. $4.00 per million queries and mutations, $2.00 per million real-time updates, $0.08 per million connection-minutes.

Azure API Management

managed

Passes GraphQL through to an existing server, or builds a synthetic GraphQL API from a schema with resolvers that call HTTP backends.

Firebase Data Connect

managed

Google’s managed GraphQL API over Cloud SQL for PostgreSQL, with generated, type-safe SDKs for web and mobile apps.

Editions of the specification#

The spec is published as dated editions at spec.graphql.org, with a working draft in between. Seven editions have appeared since 2015.

StatusNotable changes
July 2015Working draft, technical previewFirst public release, published as a work in progress
October 2015Working draftFirst of the tagged releases with a changelog, after three months of feedback
April 2016Working draftMostly clarifications; directive introspection reports locations instead of three booleans
October 2016Working draft, preview label removedThe null literal, full algorithms for execution, unique directives per location
June 2018First edition no longer a “Draft RFC”The type system definition language (SDL), subscriptions, error paths, block strings, extensions on errors; relicensed under OWFa 1.0
October 2021First edition ratified by the GraphQL FoundationInterfaces implementing interfaces, repeatable directives, @specifiedBy URLs for custom scalars
September 2025Current editionOneOf input objects, schema coordinates, descriptions on queries and other executable documents, wider deprecation, full Unicode
  • Dates and changes from each edition’s release notes on GitHub and the September 2025 announcement, checked on 2026-10-09.

See it in a real stack

No architecture uses GraphQL yet. Drop it into the playground and wire it up yourself.Open playground →
Where it came from2012–2026

In 2012 Facebook began rebuilding its iOS and Android apps, which until then were thin wrappers around the mobile website and often slow and crash-prone. Native apps needed News Feed as data, not HTML. The team looked at RESTful resources and FQL, Facebook’s SQL-like API, and was frustrated by the gap between the data the apps wanted and the server queries they had to make. A few engineers started the project that became GraphQL, and a native iOS News Feed built on it shipped that year.

Facebook released a working draft of the spec and GraphQL.js as a “technical preview” in July 2015, after the excitement around Relay, its GraphQL-based app framework. By then GraphQL served hundreds of billions of API calls a day inside Facebook. In September 2016 it dropped the preview label, the day GitHub announced the first major public GraphQL API.

In September 2017 Facebook relicensed the spec under the Open Web Foundation Agreement and GraphQL.js under MIT, dropping the separate patent grant that had come with its BSD licence. In November 2018 the Linux Foundation announced a GraphQL Foundation with members including Airbnb, Apollo, GitHub, Shopify and Twitter, and from March 2019 the spec has been developed under the Joint Development Foundation.

Why it’s built this way

A protocol, not a database
Facebook already had feed ranking, storage and business logic. So each field is backed by a function that can call any existing code, and GraphQL provides no storage of its own.
Queries shaped like the screen
A query follows relationships between objects in one request, where a RESTful service might need several round trips, which are expensive on mobile networks. The response mirrors the query.
A strongly typed, introspective schema
Typed fields let the server reject bad queries with clear errors before running them and suited the typed Objective-C and Java apps. Because the schema can be queried, tools like GraphiQL and Relay can build on it.
No version numbers
The client’s query decides the shape of the data, so new fields don’t affect existing clients and old ones can be deprecated but keep working. In 2015 Facebook said it still supported three years of app releases on one version of its API.

Timeline

  1. 2012

    Built at Facebook for the native News Feed on iOS

  2. 2015

    Draft spec and GraphQL.js released as a technical preview in July

  3. 2016

    Preview label dropped; GitHub launches a public GraphQL API

  4. 2017

    Spec relicensed under OWFa 1.0, GraphQL.js under MIT

  5. 2019

    GraphQL Foundation launches under the Linux Foundation

  6. 2025

    September edition of the spec, the first since 2021

  7. 2026

    GraphQL.js v17 released in June

Sources40 · facts checked 9 October 2026

Improve this page on GitHub