GraphQL vs REST: os mesmos dados buscados dos dois jeitos | We.Inc
Compare GraphQL e REST com os mesmos dados buscados dos dois jeitos: número de requisições, over-fetching, cache, como os erros voltam e uma tabela para escolher um deles.
REST expõe muitas URLs, uma por recurso, e o servidor decide o que cada resposta contém. GraphQL expõe um único endpoint, geralmente /graphql, para onde o cliente envia uma query que lista exatamente os campos que quer. REST ganha cache HTTP de graça pela URL; GraphQL economiza idas e voltas e corta campos não usados, ao custo de mais trabalho no servidor.
Visão geral
Tema
REST
GraphQL
Endpoints
Uma URL por recurso
Um endpoint, muitas vezes /graphql
Quem escolhe os campos
O servidor
O cliente, na query
Dados relacionados
Muitas vezes várias requisições
Aninhados em uma query
Cache HTTP
Embutido para GET pela URL
Exige queries GET, persisted queries ou cache no cliente
Erros
Principalmente códigos de status HTTP
Um array errors, muitas vezes junto de dados parciais
Schema
Opcional (OpenAPI)
Obrigatório e tipado
A comparação abaixo busca a mesma tela de dados dos dois jeitos. Escolha um cenário para ver as chamadas REST que um cliente faria ao lado da única query GraphQL que as substitui, e o que cada resposta deixa de fora ou acrescenta.
Escolha um cenário, como uma página de perfil com posts recentes.
Leia as requisições REST à esquerda e a query GraphQL à direita.
Compare o número de requisições mostrado abaixo dos painéis.
Leia a nota para ver onde cada estilo envia mais dados do que a tela precisa.
Não troque uma API REST que funciona por GraphQL só por moda. O ganho aparece quando muitas telas diferentes precisam de recortes diferentes de dados relacionados.
Exponha um campo id estável em todo tipo GraphQL para que as bibliotecas de cliente possam normalizar o cache por ele.
Confira o array errors em toda resposta GraphQL, mesmo quando o status é 200 e há dados.
Coloque limites de profundidade e de custo em um endpoint GraphQL público, já que uma única query aninhada pode pedir muito trabalho.
Perguntas frequentes
GraphQL é mais rápido que REST?
Não por si só. Ele pode reduzir idas e voltas e o tamanho do payload em telas que precisam de dados relacionados, mas cada query pode custar mais para o servidor resolver. Um endpoint REST bem projetado para uma tela pode ser igualmente rápido.
Por que um erro de GraphQL volta com status 200?
Um campo pode falhar enquanto outros dão certo, então o servidor devolve os dados que tem mais um array errors. A orientação de GraphQL over HTTP usa 2xx para sucesso parcial; servidores que respondem com application/graphql-response+json usam 400 quando uma requisição falha na validação.
Respostas GraphQL podem ficar em cache em uma CDN?
Sim, se as queries forem enviadas com GET, o que os servidores podem permitir apenas para queries. Queries longas podem passar do limite de tamanho da URL, então os times usam persisted queries, que enviam um hash curto em vez do documento inteiro.
Posso usar os dois no mesmo produto?
Muitos times fazem isso. Upload de arquivos, webhooks e recursos públicos simples costumam ficar como rotas REST, enquanto as telas do app leem por uma camada GraphQL que pode chamar esses mesmos serviços por baixo.
GraphQL precisa de um banco de dados próprio?
Não. Um servidor GraphQL é uma camada de resolvers, pequenas funções que buscam cada campo onde quer que o dado esteja: um banco de dados, um serviço REST ou um arquivo. O schema descreve formatos, não armazenamento.
Over-fetching e under-fetching
Um endpoint REST devolve um formato fixo. Uma tela de lista que mostra só nomes ainda baixa todos os campos de cada usuário, o que é over-fetching. Uma tela de detalhe que precisa de um usuário, dos posts dele e da contagem de comentários de cada post pode precisar de várias chamadas, o que é under-fetching.
GraphQL passa essa escolha para o cliente. A query lista os campos, e o servidor devolve esse formato e nada mais. A contrapartida é que o servidor precisa lidar com qualquer combinação de campos que um cliente possa pedir.
O cache funciona de outro jeito
Com REST, uma URL é uma chave de cache. Navegadores e CDNs podem guardar uma resposta GET e reutilizá-la, porque GET e HEAD são os métodos cacheáveis. A maior parte do tráfego GraphQL é POST para uma única URL, que esses caches não guardam.
Os clientes GraphQL compensam isso dentro do app: dividem as respostas em objetos e os guardam por id, então duas queries que tocam o mesmo usuário compartilham um único registro em cache. O graphql.org recomenda um campo id globalmente único exatamente por esse motivo.
Erros e códigos de status
REST se apoia na linha de status: 404 para um registro inexistente, 401 quando não há login, 422 para entrada inválida. Os clientes podem decidir o que fazer só pelo código.
Uma resposta GraphQL tem uma chave data, uma chave errors ou as duas. Um problema de sintaxe ou de validação gera errors e nenhum data. Uma falha dentro de um campo gera dados parciais com esse campo como null, e uma entrada de erro cujo path aponta para ele.
Qual escolher
Tabela de decisão
Sua situação
Tende para
API pública que terceiros chamam com curl
REST
Muitas telas, cada uma precisando de dados relacionados diferentes
GraphQL
Muito cache de CDN no tráfego de leitura
REST, ou GraphQL com persisted queries via GET
Clientes mobile em redes lentas
GraphQL, menos idas e voltas
CRUD simples sobre poucas tabelas
REST
Vários serviços de backend atrás de uma única porta de entrada
GraphQL como camada de gateway
O que trafega na rede
Uma requisição GraphQL com fetch
Toda operação é um POST de JSON com as chaves query e variables para o único endpoint. O cabeçalho Accept pede o tipo de resposta GraphQL mais novo, com JSON simples como alternativa.
Uma resposta GraphQL parcial
Um campo falhou, então ele está null e a entrada em errors o identifica com path. O resto dos dados chegou mesmo assim.
Perfil com posts
REST precisa de uma segunda chamada para os posts, e as duas respostas trazem todos os campos que o servidor inclui. A query GraphQL devolve só o nome, o avatar e três títulos de posts.
Só nomes
Para uma lista simples, a chamada REST é uma requisição de qualquer forma, mas envia os registros completos dos usuários. GraphQL envia só os dois campos pedidos.
Post com comentários e autores
Sem um endpoint personalizado, REST percorre a árvore um nível por requisição, e buscar o autor de cada comentário pode significar mais uma chamada por comentário. GraphQL aninha a árvore inteira em uma query.
Criar um post
As escritas se parecem: uma requisição cada. REST usa o método POST em uma URL de coleção; GraphQL envia uma mutation, ainda como HTTP POST, e escolhe quais campos do novo post devolver.