Introduction to GraphQL
Learn what GraphQL is, why to use it, and how it differs from REST.
What is GraphQL?
GraphQL is an open-source query language for APIs and a server runtime for fulfilling those queries.
┌─────────────────────────────────────────────────────────────────────┐
│ GRAPHQL AT A GLANCE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ • Query language for APIs (not databases) │
│ • Single endpoint for all operations │
│ • Client specifies exactly what data it needs │
│ • Server returns JSON matching the query shape │
│ • Strongly typed schema as the contract │
│ │
└─────────────────────────────────────────────────────────────────────┘
GraphQL isn't tied to any specific database or storage engine - it sits in front of your existing code and data.
The Core Idea
GraphQL comprises two parts:
- Query Language - clients specify what data they need
- Server Runtime - executes requests against a schema
Request Flow
┌─────────────────────────────────────────────────────────────────────┐
│ GRAPHQL REQUEST FLOW │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Client sends a GraphQL query │
│ │ │
│ ▼ │
│ 2. Server validates query against the Schema │
│ │ │
│ ▼ │
│ 3. Resolvers fetch data from databases, REST APIs, etc. │
│ │ │
│ ▼ │
│ 4. Server returns JSON containing only requested fields │
│ │
└─────────────────────────────────────────────────────────────────────┘
GraphQL vs REST
Most developers are familiar with REST, so let's compare the two approaches.
The Scenario
We want to display a page listing movies with their titles, release years, reviews, and awards.
REST Approach
With REST, we typically need multiple requests:
┌─────────────────────────────────────────────────────────────────────┐
│ REST: MULTIPLE REQUESTS │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Request 1: GET /movies │
│ Response: All movie fields (many unused) │
│ │
│ Request 2: GET /movies/reviews?movieIds=1,2 │
│ Response: All review fields (many unused) │
│ │
│ Request 3: GET /movies/awards?movieIds=1,2 │
│ Response: All award fields (many unused) │
│ │
│ Problems: │
│ ❌ Multiple round trips │
│ ❌ Over-fetching (unused fields) │
│ ❌ Under-fetching (need more endpoints) │
│ │
└─────────────────────────────────────────────────────────────────────┘
GET /movies
[
{
"id": 1,
"title": "Star Wars: Episode IV",
"genre": "Adventure Epic",
"releaseYear": 1977,
"durationMinutes": 121,
"originalTitle": "Star Wars",
"summary": "Luke Skywalker joins forces with a Jedi Knight..."
}
]
GET /movies/reviews?movieIds=1
[
{
"id": 111,
"movieId": 1,
"rating": 9.5,
"title": "Visually stunning sci-fi",
"comment": "The story starts slow but really pays off.",
"userId": 42,
"createdAt": "2024-06-12T14:23:00Z"
}
]
GET /movies/awards?movieIds=1
[
{
"id": 111,
"movieId": 1,
"name": "Oscar",
"category": "Best Picture",
"status": "NOMINATED"
}
]
GraphQL Approach
With GraphQL, one request gets exactly what we need:
┌─────────────────────────────────────────────────────────────────────┐
│ GRAPHQL: SINGLE REQUEST │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Request: POST /graphql (with query specifying fields) │
│ Response: Only the requested fields │
│ │
│ Benefits: │
│ ✅ Single round trip │
│ ✅ No over-fetching │
│ ✅ Client controls the shape │
│ │
└─────────────────────────────────────────────────────────────────────┘
Query:
query {
movies {
title
releaseYear
reviews {
rating
}
awards {
name
category
}
}
}
Response:
{
"data": {
"movies": [
{
"title": "Star Wars: Episode IV",
"releaseYear": 1977,
"reviews": [
{ "rating": 9.5 },
{ "rating": 9.8 }
],
"awards": [
{ "name": "Oscar", "category": "Best Picture" }
]
}
]
}
}
The response shape mirrors the query shape exactly.
The Schema (The Contract)
A GraphQL service is defined by a schema - the contract between clients and server.
Here's a simplified schema for our movie example:
type Movie {
id: ID!
title: String!
releaseYear: Int!
reviews: [Review!]!
awards: [Award!]!
}
type Review {
id: ID!
rating: Float!
comment: String
}
type Award {
id: ID!
name: String!
category: String!
status: AwardStatus!
}
enum AwardStatus {
NOMINATED
WON
}
type Query {
movies: [Movie!]!
movie(id: ID!): Movie
}
Don't worry if this looks unfamiliar - we'll explore schemas in depth in the next chapter.
Key Differences
| Aspect | REST | GraphQL |
|---|---|---|
| Endpoints | Multiple (one per resource) | Single (/graphql) |
| Data shape | Server decides | Client decides |
| Fetching | Often over/under-fetches | Precise fetching |
| Versioning | URL versioning (/v1/, /v2/) | Schema evolution |
| Documentation | External (OpenAPI, etc.) | Built-in (introspection) |
When to Use GraphQL
GraphQL excels when:
- Multiple clients need different data shapes (web, mobile, etc.)
- Complex UIs require data from multiple sources
- Rapid iteration demands flexible APIs
- Network efficiency matters (mobile, slow connections)
GraphQL may not be the best fit when:
- Simple CRUD with few clients
- File uploads are primary use case
- Caching at HTTP level is critical
Summary
| Concept | Description |
|---|---|
| GraphQL | Query language for APIs with a server runtime |
| Single endpoint | All operations go through one URL |
| Client-driven | Clients specify exactly what they need |
| Schema | Typed contract defining the API |
| Response shape | Mirrors the query structure |
What's Next?
In the next chapter, we'll explore the History of GraphQL - how it was created at Facebook and evolved into a mainstream API technology.