GraphQL

GraphQL Fundamentals And Thinking In Graphs

The Core Idea: Ask For Shapes, Get Shapes Back

A GraphQL request is a text document describing fields. The response is JSON that mirrors the request almost exactly.

Suppose we are building a music-catalog API. A client that needs an artist's name and the titles of their albums sends:

{
  artist(slug: "nova-tide") {
    name
    albums {
      title
    }
  }
}

The server answers with the same structure, filled in:

{
  "data": {
    "artist": {
      "name": "Nova Tide",
      "albums": [
        { "title": "Glasswork" },
        { "title": "Signal Fires" }
      ]
    }
  }
}

Notice what did not happen. The client did not receive fields it never asked for (no biography, no foundedYear), and it did not need a second request to fetch the albums. This is the pitch in miniature: no over-fetching, no under-fetching, one round trip.

The Three Moving Parts

Every GraphQL system has the same three pieces:

  1. A schema. The server publishes a type system: which types exist (Artist, Album, Review), which fields each type has, and what the entry points are. The schema is a contract — the server cannot return something outside it, and the client cannot ask for something outside it.
  2. Queries (and mutations, and subscriptions). Clients send documents written against the schema. Reads are queries, writes are mutations, and live streams of events are subscriptions.
  3. Resolvers. On the server, each field is backed by a function that knows how to produce that field's value — from a database, another API, a cache, anywhere. GraphQL itself does not talk to storage; your resolver code does.

A useful mental model: the schema is the map, the query is the route a client traces on the map, and resolvers are the vehicles that actually drive each leg.

It Is A Graph, Not A List Of Endpoints

REST encourages thinking in resources and URLs: /artists/42, /artists/42/albums, /albums/7/reviews. GraphQL encourages thinking in entities and relationships: an Artist has albums, an Album has tracks and reviews, a Review has an author who is a User — and a User has favoriteArtists, which loops back to Artist. Your business domain is a graph of connected things, and the schema should model those things and edges directly.

Practical consequences of graph thinking:

  • Model the domain, not the UI and not the database. If your schema mirrors one screen of your app, the next screen will not fit; if it mirrors your tables, every schema change couples to a migration. Name types after business concepts your team already uses.
  • One graph, many entry points. Fields on the root Query type (artist, album, search) are just doorways into the same connected graph. Once inside, a client can traverse edges as deep as it needs.
  • You do not need the whole graph on day one. Ship the types one client needs now; add types and fields later. Adding to a schema is backwards-compatible, which is why GraphQL APIs typically evolve without versioned URLs like /v2/.

Strongly Typed, End To End

Every field in a schema has a type — String, Int, Boolean, a custom object type, a list, and so on — and every field can be marked non-nullable. Because both sides share the schema:

  • the server can reject a malformed query before running any code (validation),
  • tools can autocomplete queries and type-check client code against the schema,
  • documentation is generated from the schema itself rather than maintained by hand.

This is a different trade than a typical JSON-over-REST API, where the response shape lives in documentation (or in someone's memory) and drift between docs and reality is common.

Where GraphQL Runs

GraphQL is a specification, not a product and not a database. Implementations exist in most languages — in PHP the reference implementation is the webonyx/graphql-php library, which later lessons in this track use. The transport is usually HTTP with JSON responses, but the spec does not require HTTP; the same query could travel over a WebSocket or a message queue.

It is also not tied to any storage engine. A single query about an artist might be resolved from MySQL, with the review counts coming from Redis and the streaming stats from a third-party REST API — the client never knows or cares.

When GraphQL Is A Good Fit (And When It Is Not)

Reach for GraphQL when:

  • multiple clients (web, mobile, partners) need different slices of the same data,
  • screens aggregate several related entities and REST would need many round trips or bloated "expand" parameters,
  • you want a typed contract and tooling between frontend and backend teams.

Be cautious when:

  • you have one internal client and simple CRUD needs — REST or RPC is less machinery,
  • responses must be aggressively HTTP-cached by URL (a later lesson covers why GraphQL makes this harder),
  • the team is not prepared to manage query cost — flexible queries mean clients can accidentally write expensive ones.

What To Check

Before moving on, make sure you can:

  • explain what a schema, a query, and a resolver each do
  • describe over-fetching and under-fetching and how GraphQL addresses both
  • contrast resource-and-URL thinking with entity-and-relationship thinking
  • explain why GraphQL APIs usually evolve by adding fields instead of versioning URLs
  • name situations where GraphQL is the wrong tool

What You Should Be Able To Do

After this lesson, you should be able to read a simple GraphQL query and predict the JSON shape of its response, sketch a small domain (like a music catalog) as types and relationships rather than endpoints, and articulate to a teammate what problems GraphQL solves that a plain REST API does not — and what new problems it introduces.