1. Library
  2. Http and the Web
  3. Modern Protocols

Updated 10 hours ago

In 2012, Facebook's mobile app was struggling. Users scrolled through their feeds, and the app made request after request—one for posts, another for comments, another for likes, another for user details. Each round-trip added latency. On cellular networks, the experience was painful.

The engineering team faced a choice: keep patching their REST API with more specialized endpoints, or rethink the whole approach. They chose to rethink. In 2015, they released GraphQL.

This wasn't just a technical upgrade. It represented a fundamentally different answer to a question every API must answer: who decides what data travels over the wire?

The Core Difference

REST says: the server decides what you get.

GraphQL says: the client decides what it needs.

Every other difference flows from this.

How REST Works

REST organizes APIs around resources—users, posts, comments—each at its own URL. You request a resource, you get that resource. The shape of the response is fixed by whoever built the endpoint.

GET /users/123          → Returns all fields the server includes
GET /users/123/posts    → Returns posts with all their fields
GET /posts/456/comments → Returns comments with all their fields

Want to display a user's profile with their recent posts and the comments on those posts? Three requests minimum. Want just the user's name and email, not their entire profile? Too bad—you get everything or nothing.

This is the server deciding. The endpoint author chose what to include. You accept their choice.

How GraphQL Works

GraphQL exposes a single endpoint. Instead of requesting resources by URL, you send a query describing exactly what you want:

query {
  user(id: "123") {
    name
    email
    posts {
      title
      comments {
        text
        author {
          name
        }
      }
    }
  }
}

One request. The response contains exactly what you asked for—the user's name and email, their posts' titles, each post's comments, and each comment author's name. Nothing more, nothing less.

This is the client deciding. You specify the shape. The server fulfills your specification.

Why This Difference Matters

The Bandwidth Problem

Request a user from a REST API, and you might get 30 fields when you need 3. This is over-fetching—receiving more data than necessary. On a fast office connection, who cares? On a cellular network in rural Indonesia, it's the difference between a responsive app and one users abandon.

GraphQL eliminates over-fetching by design. You ask for three fields, you get three fields.

The Round-Trip Problem

Display a complex UI component—say, a dashboard with user info, recent activity, notifications, and recommendations. With REST, you might need 5-10 separate requests. Each request adds latency. On a connection with 200ms round-trip time, that's 1-2 seconds of waiting before anything renders.

GraphQL collapses those requests into one. The query might be larger, but the latency happens once, not ten times.

The Flexibility Problem

Your mobile app needs minimal data to conserve bandwidth. Your web app needs rich data for a full-featured experience. Your admin dashboard needs everything.

With REST, you face unpleasant choices: create separate endpoints for each client, return everything and let clients ignore what they don't need, or accept that some clients get suboptimal responses.

With GraphQL, each client writes queries for exactly what it needs. The API doesn't change. The clients just ask different questions.

The Versioning Problem

Change a REST endpoint's structure, and you risk breaking every client that depends on it. This leads to version proliferation—/v1/users, /v2/users, /v3/users—and the maintenance burden of supporting them all.

GraphQL handles evolution differently. Add new fields freely; existing queries don't break because they don't ask for the new fields. Remove old fields by marking them deprecated; the schema documents this, and clients can migrate gradually. No version explosion.

Where GraphQL Hurts

Caching Becomes Hard

REST rides on HTTP, and HTTP has built-in caching. GET /users/123 can be cached by browsers, CDNs, and proxies based on the URL. Change nothing, and the cache serves repeated requests instantly.

GraphQL requests are POST requests to /graphql with queries in the body. Standard HTTP caching doesn't apply. You need specialized caching strategies—persisted queries, response caching, normalized caches—that require thought and implementation.

The N+1 Problem

Here's a nightmare scenario. A client sends this query:

query {
  posts {
    author {
      name
    }
  }
}

Looks innocent. But if you have 100 posts, a naive implementation fetches the posts (1 query), then fetches each author individually (100 queries). That's 101 database calls for one GraphQL query.

This is the N+1 problem, and it will destroy your database if you don't solve it. Tools like DataLoader batch these requests, but they require understanding and careful implementation. Get it wrong, and one clever client query brings your servers to their knees.

Complexity Compounds

REST APIs can be built with minimal tooling. Define some routes, return some JSON, done.

GraphQL requires a schema definition, resolver functions for every field, a query execution engine, and understanding of concepts like fragments, variables, and directives. The learning curve is real. The operational complexity is higher.

Rate Limiting Gets Weird

With REST, rate limiting is straightforward: allow 100 requests to /users per hour. Simple.

GraphQL has one endpoint. A query fetching one field and a query fetching the entire database look identical to naive rate limiting. You need query complexity analysis—calculating the "cost" of each query and limiting by cost rather than count. This is solvable but not simple.

Where REST Shines

Simplicity Wins Sometimes

URLs map to resources. HTTP methods map to operations. GET /users gets users. POST /users creates one. This mental model fits in one sentence. New developers understand it immediately.

For simple APIs—a few resources, straightforward CRUD operations—GraphQL's machinery is overhead without benefit.

Caching Just Works

If your API serves the same data repeatedly—product listings, public content, reference data—HTTP caching provides massive performance wins for free. CDNs cache your responses. Browser caches serve repeated requests instantly. No additional implementation required.

The Ecosystem is Mature

REST has existed for over two decades. Every language has HTTP libraries. Every debugging tool handles it. Every developer has used it. This maturity means fewer surprises, more resources, easier hiring.

Public APIs Have Conventions

External developers expect REST. They know HTTP status codes, content negotiation, standard authentication patterns. Documentation conventions exist. GraphQL requires them to learn something new—a barrier for API adoption.

Choosing Based on Reality

GraphQL makes sense when:

  • Your UI needs data from many resources in single views
  • Mobile performance matters (bandwidth and latency)
  • Multiple clients need different data from the same API
  • Frontend teams want to iterate without waiting for backend changes
  • You're aggregating data from multiple microservices

REST makes sense when:

  • Your API is resource-oriented with simple operations
  • HTTP caching is critical to your performance strategy
  • You're building a public API for external developers
  • Your team knows REST but would need to learn GraphQL
  • File uploads and downloads are central operations

You can use both:

Many organizations do. REST for public APIs and file handling. GraphQL for mobile apps and complex internal tooling. The approaches aren't mutually exclusive.

The Facebook Question

Remember where we started? Facebook had a mobile app making too many requests, transferring too much data, suffering on cellular networks.

GraphQL solved that specific problem. It lets clients ask for exactly what they need in a single request. For Facebook's use case—complex social data, mobile-first, many different clients—it was the right answer.

But not every problem is Facebook's problem. If your API serves simple, cacheable resources to web browsers on fast connections, REST's simplicity and caching advantages might matter more than GraphQL's flexibility.

The question isn't which approach is better. The question is: who should decide what data travels over the wire? And for your specific users, on your specific networks, with your specific data requirements—what's the right answer?

Frequently Asked Questions About GraphQL vs. REST

Was this page helpful?

😔
🤨
😃