Skip to main content
Back to blog

REST vs GraphQL in practice

·3 min readWeb Dev

I have built APIs with both REST and GraphQL. The internet loves to frame this as a debate, but in practice the choice is straightforward: it depends on your client's data needs.

When REST wins

REST is the default for a reason. It is simple, well-understood, and every developer knows how to work with it. For most APIs, REST endpoints that return well-shaped JSON responses are all you need.

// Clean, predictable, easy to cache
GET /api/users/123
GET /api/users/123/posts
GET /api/posts?category=tech&limit=10

REST shines when:

  • Your data model maps naturally to resources (users, posts, products)
  • You have a small number of clients with predictable data needs
  • You want HTTP caching to work out of the box
  • Your team is small and does not want to maintain a schema

When GraphQL wins

GraphQL solves a real problem: when different clients need different shapes of the same data. A mobile app might need a user's name and avatar. A dashboard might need the same user's name, email, role, and last 10 actions. A report might need aggregate stats.

With REST, you either create multiple endpoints, add query parameters for field selection, or return everything and let the client ignore what it does not need. GraphQL lets the client ask for exactly what it wants:

# Mobile app
query {
  user(id: "123") {
    name
    avatarUrl
  }
}
 
# Dashboard
query {
  user(id: "123") {
    name
    email
    role
    recentActions(limit: 10) {
      type
      timestamp
    }
  }
}

One endpoint, one schema, different responses based on what the client asks for.

The hidden costs of GraphQL

Complexity. You need a schema definition, resolvers, a query execution engine, and often a code generation step for type safety. For a simple CRUD API, this is significant overhead.

Caching. HTTP caching does not work naturally with GraphQL because everything is a POST to a single endpoint. You need application-level caching (Apollo Client, urql) or persisted queries.

N+1 queries. A naive GraphQL resolver for "users with their posts" will execute one database query per user to fetch their posts. You need DataLoader or similar batching to avoid this.

Security. Clients can write deeply nested queries that consume significant server resources. You need query depth limiting, complexity analysis, or persisted queries to prevent abuse.

What I use in practice

For most of my projects, REST is the answer. The simplicity wins. I use REST for Landbound's API because the data access patterns are predictable and I do not need multiple clients with different data needs.

I reach for GraphQL when I am building a product with multiple frontends (web, mobile, third-party integrations) that need different views of the same data. The upfront investment in the schema pays off when you stop maintaining separate endpoints for each client.

The pragmatic approach

Start with REST. If you find yourself creating increasingly specific endpoints for different clients or adding complex query parameters for field selection, consider GraphQL. Do not adopt it because it is trendy. Adopt it because your data access patterns demand it.

Sources

Enjoying the blog? Subscribe via RSS to get new posts in your reader.

Subscribe via RSS