What is GraphQL?

April 15, 2026

We will be starting to learn about GraphQL and using it in an iOS App

In this next few articles we will be starting to learn about GraphQL and using it in an iOS App. I will assume you know nothing about GraphQL about

Imagine you are ordering food at a restaurant. With a traditional approach, you get a fixed meal — maybe a burger, fries, and a drink — whether you wanted the fries or not. You have no control over what comes on the plate. That is how REST APIs work: you call an endpoint, and the server decides exactly what data to send back.

Now imagine a restaurant where you write your own order from scratch. You say: "I want the burger, hold the fries, add extra pickles, and give me a milkshake instead of water." The kitchen gives you exactly what you asked for — nothing more, nothing less. That is GraphQL.

GraphQL (Graph Query Language) is a query language for APIs invented by Facebook in 2012 and open-sourced in 2015. Instead of the server deciding what shape the data takes, the client decides. You write a query describing exactly the data you need, send it to a single endpoint, and receive a JSON response that mirrors the shape of your query.

GitHub was one of the earliest major adopters of GraphQL. They built their entire v4 API using GraphQL because their REST API (v3) was struggling with the complexity of the data relationships between users, repositories, issues, pull requests, and more. With REST, fetching a repository's details alongside its issues and contributors required multiple round-trips. With GraphQL, it is a single query.

The Three Pillars of GraphQL

Queries — Reading Data

A query is how you ask a GraphQL server for data. Think of it as a GET request, but far more flexible. Here is a simple query that asks GitHub for your username and bio:

query {
  viewer {
    login
    bio
    avatarUrl
  }
}

And the server responds with:

{
  "data": {
    "viewer": {
      "login": "octocat",
      "bio": "I love coding!",
      "avatarUrl": "https://avatars.githubusercontent.com/u/123456"
    }
  }
}

Notice how the response shape mirrors the query shape exactly. This is one of GraphQL's most powerful features — you always know what you are going to get back.

Mutations — Writing Data

Mutations are how you create, update, or delete data on the server. They are like POST, PUT, or DELETE in REST. For example, starring a repository on GitHub:

mutation {
  addStar(input: { starrableId: "MDEwOlJlcG9zaXRvcnkxMjM0NTY=" }) {
    starrable {
      stargazerCount
    }
  }
}

Every mutation requires an input object (the data you are sending) and returns a payload (the data you want back after the change is made).

Subscriptions — Real-Time Data

Subscriptions let you listen for real-time updates over a WebSocket connection. When data changes on the server, your client gets notified automatically. GitHub's public GraphQL API does not currently support subscriptions, but we will discuss the concept and how Apollo iOS handles them.

Key Vocabulary

Term What It Means Analogy
Schema The contract defining all available types and fields A restaurant's complete menu
Query A request for specific data Your food order
Mutation A request to change data Asking the chef to modify a dish
Subscription A real-time listener for data changes A waiter bringing you updates
Resolver Server function that fetches data for a field The chef cooking your order
Type A shape of data (like a Swift struct) A category on the menu
Field A single piece of data on a type An item within a category
Argument A parameter passed to a field "Extra pickles, no onion"
Fragment A reusable set of fields A combo meal you can reference anywhere
Node An object with a global ID A specific dish with a ticket number
Edge A relationship between two nodes The link between "dish" and "ingredient"
Connection A paginated list of edges A multi-page section of the menu

How a GraphQL Request Works Under the Hood

Every GraphQL request, regardless of whether it is a query or mutation, follows the same HTTP pattern:

  1. HTTP Method: Always POST (the operation type is defined inside the body, not by the HTTP verb)
  2. Endpoint: Always the same URL — for GitHub, it is https://api.github.com/graphql
  3. Headers: Must include Authorization: Bearer YOUR_TOKEN and Content-Type: application/json
  4. Body: A JSON object with a query string (your GraphQL operation), and optionally variables and operationName
POST https://api.github.com/graphql
Authorization: Bearer ghp_xxxxxxxxxxxx
Content-Type: application/json

{
  "query": "query { viewer { login } }",
  "variables": {},
  "operationName": null
}

GraphQL vs REST — A Detailed Comparison

If you have ever built an iOS app, you have almost certainly used REST APIs. Understanding how GraphQL differs from REST will help you appreciate why companies like GitHub, Shopify, and Yelp have adopted it.

Endpoints

REST: Each resource has its own URL. To get a GitHub user, you call GET /users/octocat. To get their repos, you call GET /users/octocat/repos. To get a specific repo's issues, you call GET /repos/octocat/hello-world/issues. Three different endpoints, three separate network calls.

GraphQL: There is one single endpoint: https://api.github.com/graphql. Every request goes to the same address. The query you write in the request body determines what data you get back. You could fetch the user, their repos, and the issues on those repos in a single request.

Over-Fetching and Under-Fetching

Over-fetching means getting more data than you need. GitHub's REST endpoint for a repository returns over 100 fields — owner info, license details, permissions, URLs for every resource — even if you only need the name and star count.

Under-fetching means not getting enough data in one call. To show a GitHub profile page with the user's info, their pinned repos, and recent contributions, you might need 4–5 separate REST calls. Each call adds latency, especially on mobile networks.

GraphQL eliminates both problems. You specify exactly which fields you need, and you get everything in one round-trip.

A Concrete Example with GitHub

Imagine building a screen that shows a GitHub user's name, avatar, and their 5 most recent repositories with star counts.

With REST (3 requests):

GET /users/octocat                     → 100+ fields, you need 3
GET /users/octocat/repos?per_page=5    → 80+ fields per repo, you need 2
GET /users/octocat/repos?sort=updated  → Might not give you what you need

With GraphQL (1 request):

query {
  user(login: "octocat") {
    name
    avatarUrl
    repositories(last: 5, orderBy: { field: UPDATED_AT, direction: DESC }) {
      nodes {
        name
        stargazerCount
      }
    }
  }
}

One request. Exactly the fields you need. No wasted bandwidth.

Side-by-Side Comparison

Feature REST GraphQL
Endpoints Many (one per resource) One (single endpoint)
Data shape Decided by the server Decided by the client
Over-fetching Common problem Eliminated by design
Under-fetching Requires multiple calls Single query gets all data
Versioning Often /v1/, /v2/, /v3/ Schema evolves, no versioning needed
Documentation Swagger/OpenAPI (separate) Schema IS the documentation (introspection)
Type safety Requires separate type definitions Built into the schema
Error handling HTTP status codes (404, 500) Always returns 200; errors in response body
Caching HTTP caching (ETags, Cache-Control) Requires a smart client (Apollo)
File uploads Straightforward (multipart) Requires special handling
Learning curve Low (very familiar) Moderate (new syntax and concepts)