GraphQL is a query language for APIs and a runtime that executes those queries. Instead of having many REST endpoints (/users, /users/1/posts, /users/1/posts/5/comments), you have one endpoint and clients ask for exactly the data they need — nothing more, nothing less.
REST vs GraphQL
With REST, fetching a user's profile plus their latest three posts might require two requests:
GET /users/42
GET /users/42/posts?limit=3With GraphQL, one request:
query {
user(id: 42) {
name
email
posts(limit: 3) {
title
publishedAt
}
}
}The server returns exactly that shape — no extra fields, no under-fetching.
The Schema
Everything in GraphQL is defined in a schema — a typed contract between client and server:
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
publishedAt: String!
author: User!
}
type Query {
user(id: ID!): User
posts: [Post!]!
}! means non-nullable. [Post!]! means a non-null list of non-null Post objects.
Scalar Types
| Type | Description |
|---|---|
String | UTF-8 text |
Int | 32-bit integer |
Float | Double-precision decimal |
Boolean | true or false |
ID | Unique identifier (serialised as String) |
You can also define custom scalars (e.g. Date, JSON).
Queries, Mutations, and Subscriptions
GraphQL has three operation types:
- Query — read data (like GET)
- Mutation — write data (like POST/PUT/DELETE)
- Subscription — real-time event stream over WebSocket
# Query
query GetUser($id: ID!) {
user(id: $id) { name email }
}
# Mutation
mutation CreatePost($title: String!, $authorId: ID!) {
createPost(title: $title, authorId: $authorId) {
id title
}
}
# Subscription
subscription OnNewPost {
postCreated { id title author { name } }
}Making a GraphQL Request
GraphQL always uses POST with Content-Type: application/json. The body contains the query string and optional variables:
Why GraphQL?
Advantages over REST:
- No over-fetching (you only get what you ask for)
- No under-fetching (get nested data in one request)
- Strongly typed schema serves as living documentation
- Introspection — clients can query the schema itself
Trade-offs:
- More complex to set up than a simple REST API
- Caching is harder (all requests go to one URL)
- File uploads require extra configuration
- N+1 query problem if resolvers aren't batched with DataLoader