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:
- 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. - 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.
- 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
Querytype (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.