What Is GraphQL?
GraphQL is a query language for APIs that lets clients request exactly the data they need — no over-fetching, no under-fetching, and a strongly typed schema as the contract.
GraphQL is a query language and runtime for APIs that lets a client ask for exactly the data it needs in a single request, against a strongly typed schema that serves as the contract between client and server. Instead of many fixed endpoints each returning a predetermined shape, GraphQL exposes one endpoint where the client describes the response it wants.
It was created at Facebook in 2012 to cut down the round-trips its mobile apps made, and open-sourced in 2015. The specification is now governed by the GraphQL Foundation.
How GraphQL works
Three ideas do most of the work:
- Schema — a typed description of every object, field, and relationship the API can return. Tools and editors read it for autocomplete and validation, so the contract is enforced before a request ever runs.
- Single endpoint — typically
POST /graphql. The query travels in the request body rather than in the URL path. - Resolvers — server functions that know how to fetch each field. The server walks the query, calls the matching resolvers, and assembles a response that mirrors the query's shape.
The three operation types are query (read), mutation (write), and subscription (a long-lived stream of updates, usually over WebSockets).
GraphQL vs REST
# GraphQL — the client controls the shape
query {
user(id: "42") {
name
email
subscriptions {
planName
status
}
}
}
With REST you might call GET /users/42 (often over-fetching fields you don't need) and then GET /users/42/subscriptions (a second round-trip). GraphQL returns both in one request, with only the fields you asked for. That solves two recurring REST problems: over-fetching (the endpoint returns more than the screen uses) and under-fetching (one screen needs several endpoints).
| GraphQL | REST | |
|---|---|---|
| Endpoints | One | Many, resource-based |
| Response shape | Defined by the client | Defined by the server |
| Typed contract | Built in (schema) | Optional (e.g. OpenAPI) |
| HTTP caching | Harder (POST) | Easy (GET + cache headers) |
| Versioning | Evolve schema, deprecate fields | New /v2 endpoints |
When GraphQL fits — and when it doesn't
Reach for GraphQL when:
- Several client types (web, mobile, third parties) need the same data in different shapes.
- The data is deeply nested or relational, so REST would need many requests to stitch together.
- A clear frontend/backend split benefits from a typed contract both sides build against.
Stay with REST when:
- You have simple CRUD with predictable shapes.
- One person owns both the API and the frontend, so a strict contract adds ceremony without payoff.
- HTTP caching matters — REST
GETresponses cache at the CDN or browser with almost no effort, while GraphQLPOSTqueries need extra setup (persisted queries, automatic persisted queries, or a normalized client cache).
Common mistakes
- Assuming GraphQL is automatically faster. It removes round-trips, but a careless query can trigger the N+1 problem — one query that fans out into hundreds of database calls. Batch with a loader (DataLoader-style) to fix it.
- Skipping query cost limits. Because clients write the queries, a deeply nested one can be expensive. Production servers add depth limits, complexity scoring, or timeouts.
- Treating it as a database. GraphQL is an API layer over whatever you already have — databases, REST services, third-party APIs. It does not replace your data store.
- Reaching for it too early. For a small SaaS MVP, REST is usually faster to ship.
In practice
Supabase exposes a GraphQL API alongside its auto-generated REST API, so you can adopt GraphQL without standing up a separate server. For most early-stage products the REST path is simpler to start with; GraphQL earns its place once you have multiple clients with meaningfully different data needs. In the SaaS projects I've shipped — BookBed, a booking platform on Flutter and Firebase, and Callidus, a clinic tool on React and Firebase — the data layer was chosen to match the client mix rather than defaulted to one style. If you're weighing GraphQL against REST for a build, contact me for a quote and I'll scope it to your actual client needs.
Key takeaways
- What it is: a typed query language for APIs where the client requests exactly the fields it needs from one endpoint.
- Why it exists: to end over-fetching and under-fetching across many client types.
- When to skip it: simple CRUD, a single full-stack owner, or when easy HTTP caching outweighs flexible queries.