GraphQL is not a replacement for REST — it’s an alternative that shines in specific scenarios. Understanding when to use each is more valuable than dogmatically choosing one.

When GraphQL Wins

  • Complex, nested data — Fetch articles with authors and comments in one request
  • Multiple client types — Mobile apps need different data than web apps
  • Rapid iteration — Frontend teams can evolve queries without backend changes

A Simple Schema

type Article {
  id: ID!
  title: String!
  content: String!
  author: User!
  comments: [Comment!]!
  createdAt: DateTime!
}

type Query {
  article(id: ID!): Article
  articles(limit: Int = 25, offset: Int = 0): [Article!]!
}

type Mutation {
  createArticle(input: CreateArticleInput!): Article!
}

The N+1 Problem

The biggest pitfall in GraphQL — and how to solve it:

# Without dataloader — N+1 queries!
field :author, Types::UserType, null: false
def author
  User.find(object.author_id)  # Called for EVERY article
end

# With dataloader — batched!
field :author, Types::UserType, null: false
def author
  dataloader.with(Sources::User).load(object.author_id)
end

Rule of thumb: If your clients need predictable, cacheable responses — use REST. If they need flexible, composed responses — consider GraphQL.