Skip to main content

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:

  1. Query Language - clients specify what data they need
  2. 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

AspectRESTGraphQL
EndpointsMultiple (one per resource)Single (/graphql)
Data shapeServer decidesClient decides
FetchingOften over/under-fetchesPrecise fetching
VersioningURL versioning (/v1/, /v2/)Schema evolution
DocumentationExternal (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

ConceptDescription
GraphQLQuery language for APIs with a server runtime
Single endpointAll operations go through one URL
Client-drivenClients specify exactly what they need
SchemaTyped contract defining the API
Response shapeMirrors 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.