What is GraphQL? — API Query Language Explained
Definition
GraphQL is a query language and runtime for APIs developed internally by Facebook in 2012 and released publicly in 2015. Unlike traditional REST APIs where the server defines the shape and structure of responses, GraphQL gives clients the power to ask for exactly what they need and nothing more.
GraphQL provides a single endpoint (typically /graphql) and a strongly typed schema that describes all available data and operations.
Queries vs Mutations vs Subscriptions
GraphQL defines three operation types:
Queries (Read Data)
Queries are used to fetch data — analogous to HTTP GET in REST:
query GetUser {
user(id: "123") {
name
email
posts {
title
createdAt
}
}
}{
"data": {
"user": {
"name": "Alice Johnson",
"email": "alice@example.com",
"posts": [
{ "title": "GraphQL Basics", "createdAt": "2026-01-15" },
{ "title": "Advanced Schema Design", "createdAt": "2026-02-20" }
]
}
}
}Mutations (Write Data)
Mutations are used to create, update, or delete data — analogous to POST, PUT, DELETE in REST:
mutation CreatePost {
createPost(input: {
title: "New Post"
content: "This is the content"
authorId: "123"
}) {
id
title
createdAt
}
}{
"data": {
"createPost": {
"id": "456",
"title": "New Post",
"createdAt": "2026-06-15T12:00:00Z"
}
}
}Subscriptions (Real-time)
Subscriptions maintain a persistent connection (via WebSocket) for real-time updates:
subscription OnNewPost {
newPost {
id
title
author {
name
}
}
}Schema and Types
GraphQL APIs are defined by a schema written in the GraphQL Schema Definition Language (SDL):
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
createdAt: DateTime!
}
type Post {
id: ID!
title: String!
content: String!
published: Boolean!
author: User!
createdAt: DateTime!
}
type Query {
user(id: ID!): User
users: [User!]!
post(id: ID!): Post
posts: [Post!]!
}
type Mutation {
createPost(input: CreatePostInput!): Post!
updatePost(id: ID!, input: UpdatePostInput!): Post!
deletePost(id: ID!): Boolean!
}
type Subscription {
newPost: Post!
}
input CreatePostInput {
title: String!
content: String!
authorId: ID!
}Built-in Scalar Types
| Type | Description |
|---|---|
Int |
Signed 32-bit integer |
Float |
Double-precision floating point |
String |
UTF-8 character sequence |
Boolean |
true or false |
ID |
Unique identifier (serialized as String) |
Type Modifiers
| Modifier | Meaning | Example |
|---|---|---|
! |
Non-nullable (value must be provided) | String! |
[Type] |
List of Type | [Post] |
[Type!] |
List of non-null items | [Post!] |
[Type]! |
Non-null list (may contain nulls) | [Post]! |
Resolvers
Resolvers are functions that provide the data for each field in the schema:
const resolvers = {
Query: {
user: (parent, args, context, info) => {
return db.users.findById(args.id);
},
posts: (parent, args, context, info) => {
return db.posts.findAll();
},
},
User: {
posts: (parent, args, context, info) => {
return db.posts.findByAuthorId(parent.id);
},
},
Mutation: {
createPost: (parent, args, context, info) => {
const post = {
id: generateId(),
...args.input,
createdAt: new Date().toISOString(),
};
return db.posts.create(post);
},
},
};Resolver Arguments
| Argument | Purpose |
|---|---|
parent |
The result of the parent resolver (for nested fields) |
args |
Arguments passed to the field in the query |
context |
Shared object across all resolvers (auth, DB, loaders) |
info |
Query AST information (advanced use) |
GraphQL vs REST
| Aspect | GraphQL | REST |
|---|---|---|
| Endpoint Model | Single endpoint (/graphql) |
Multiple endpoints (/users, /posts) |
| Data Fetching | Client specifies exact fields | Server returns fixed response shape |
| Over-fetching | None — client controls response | Common — server returns all fields |
| Under-fetching | Solved — nested queries in one request | Common — requires multiple requests |
| Versioning | None needed (add fields without breaking) | URL versioning (/v1/, /v2/) |
| Caching | Requires custom setup (Apollo, Relay) | Built-in HTTP caching |
| Tooling | Growing ecosystem (Apollo, Relay, Urql) | Mature ecosystem (Postman, Swagger) |
| Learning Curve | Moderate | Gentle |
| Best For | Complex UIs, mobile apps, rapid iteration | Public APIs, CRUD, caching-heavy apps |
Apollo Tooling
Apollo is the most popular GraphQL ecosystem, providing tools for both client and server:
Apollo Server
const { ApolloServer } = require('@apollo/server');
const { startStandaloneServer } = require('@apollo/server/standalone');
const server = new ApolloServer({
typeDefs,
resolvers,
});
startStandaloneServer(server, {
context: async ({ req }) => ({
auth: req.headers.authorization,
db,
}),
}).then(({ url }) => console.log(`Server ready at ${url}`));Apollo Client (React)
import { ApolloClient, InMemoryCache, gql } from '@apollo/client';
const client = new ApolloClient({
uri: 'https://api.example.com/graphql',
cache: new InMemoryCache(),
});
const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) {
name
email
}
}
`;
// Usage with React
function UserProfile({ userId }) {
const { loading, error, data } = useQuery(GET_USER, {
variables: { id: userId },
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return <h1>{data.user.name}</h1>;
}Real-World GraphQL Use Cases
Mobile Applications
GraphQL's precise data fetching reduces payload size — critical for mobile networks. GitHub, Shopify, and Twitter use GraphQL in their mobile apps.
Complex Dashboards
Dashboards that aggregate data from multiple sources benefit from GraphQL's ability to fetch nested data in a single request.
Microservice Aggregation
A GraphQL gateway can unify multiple backend services (microservices, legacy APIs, third-party APIs) behind a single schema.
Real-Time Features
Subscriptions enable live updates for chat, notifications, and collaborative editing.
LangStop API Tools
- REST API Client — Send HTTP requests and test API endpoints
- API Mock Response Generator — Generate realistic mock JSON responses
- JSON Formatter — Format, validate, and beautify JSON