GraphQL vs REST: quando cada um faz sentido

Entenda o problema de over-fetching e under-fetching que o GraphQL resolve, como uma query GraphQL funciona na prática comparada a um endpoint REST, e em que situação cada abordagem realmente compensa.

tecnico backend api 4 min de leitura

Já expliquei aqui o que é uma API e o que um júnior precisa saber sobre elas, mencionando GraphQL de passagem como uma das opções que existem além do REST tradicional. Vale aprofundar essa comparação, porque a diferença entre os dois não é só de sintaxe, é sobre um problema real que aparece assim que uma API cresce e atende telas diferentes com necessidades diferentes.

O problema do over-fetching

Numa API REST tradicional, cada endpoint devolve um formato fixo de dado. Um endpoint /usuarios/123 devolve o usuário inteiro, com todos os campos que existem na tabela:

{
  "id": "123",
  "nome": "Ana",
  "email": "ana@exemplo.com",
  "endereco": { "rua": "...", "cidade": "..." },
  "criadoEm": "2026-01-10",
  "ultimoLogin": "2026-09-14"
}

Se a tela que consome esse endpoint só precisa mostrar o nome e o e-mail, o resto do JSON ainda assim viaja pela rede, sem necessidade. Isso é over-fetching: buscar mais dado do que a tela realmente usa. Multiplicado por milhares de requisições, principalmente em conexão de internet mais lenta, esse excesso pesa de verdade.

O problema do under-fetching

O inverso também acontece. Se a tela precisa do usuário junto com a lista de pedidos dele, e o endpoint /usuarios/123 não devolve isso, a solução comum é fazer uma segunda requisição pra /usuarios/123/pedidos. Se além dos pedidos você também precisa dos itens de cada pedido, lá vem uma terceira requisição, e assim por diante. Isso é under-fetching: um endpoint sozinho não entrega o suficiente, forçando várias idas e vindas até juntar todo o dado que a tela precisa.

Como o GraphQL resolve os dois

O GraphQL inverte a lógica: em vez de o servidor decidir o formato fixo da resposta, quem pede é quem descreve exatamente os campos que quer, numa única requisição:

query {
  usuario(id: "123") {
    nome
    email
    pedidos {
      id
      total
    }
  }
}

A resposta vem exatamente no formato pedido, nem mais, nem menos:

{
  "data": {
    "usuario": {
      "nome": "Ana",
      "email": "ana@exemplo.com",
      "pedidos": [
        { "id": "1", "total": 150 },
        { "id": "2", "total": 89 }
      ]
    }
  }
}

Uma única requisição resolve o que, em REST, exigiria pelo menos duas (usuário e pedidos), e sem trazer o endereco ou o ultimoLogin que essa tela específica não precisa. Isso resolve over-fetching e under-fetching ao mesmo tempo, transferindo pra quem consome a decisão de quais campos vêm na resposta.

O outro lado: complexidade no servidor

Essa flexibilidade não é de graça. No REST, cada endpoint é uma rota simples, fácil de cachear (inclusive com o Data Cache do Next que já expliquei aqui), fácil de monitorar isoladamente, fácil de aplicar rate limiting específico por rota. No GraphQL, existe tipicamente um único endpoint recebendo toda query possível, o que exige mais trabalho pra evitar abuso: alguém pode escrever uma query pedindo dados profundamente aninhados (usuário, pedidos de cada usuário, itens de cada pedido, produto de cada item), gerando uma carga de processamento no servidor bem maior do que qualquer requisição REST equivalente faria sozinha.

Isso exige ferramentas próprias, como limite de profundidade de query e análise de custo de cada campo, coisa que uma API REST simples nem precisa considerar.

Quando cada um faz sentido

REST continua sendo a escolha mais simples pra APIs com poucos formatos de consumo, onde o mesmo formato de resposta atende bem a maioria dos clientes, e onde cache HTTP tradicional por rota já resolve performance sem esforço extra. Também é mais fácil de documentar, testar e depurar pra quem está começando.

GraphQL compensa quando existem clientes bem diferentes consumindo o mesmo backend (aplicativo mobile precisando de pouco dado, painel administrativo precisando de muito), ou quando a tela muda com frequência e cada mudança de design exigiria criar ou ajustar um endpoint REST novo só pra aquele formato específico.

Fechando

Não existe um sempre melhor entre os dois, existe o problema que cada API realmente tem. Se o incômodo é telas diferentes puxando dado demais ou de menos, com times de frontend pedindo endpoint novo toda semana, GraphQL resolve isso de forma estrutural. Se o sistema é mais direto, com poucos formatos de consumo, o REST tradicional continua sendo a opção mais simples de manter, sem precisar lidar com a complexidade extra que o GraphQL traz pro lado do servidor.