System Design/02 - Componentes/Communication2 min
GraphQL
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Linguagem de consulta para APIs em que o cliente declara exatamente os campos que quer, num único endpoint.
query {
usuario(id: 42) {
nome
pedidos(ultimos: 10) { id total
itens { produto { nome } }
}
}
}
Uma requisição, exatamente os campos pedidos, em qualquer profundidade.
Peças
| Peça | Papel |
|---|---|
| Schema | Contrato tipado — a fonte da verdade |
| Query | Leitura |
| Mutation | Escrita |
| Subscription | Push via WebSocket |
| Resolver | Função que resolve cada campo |
Trade-offs
| Ganha | Perde |
|---|---|
| Acaba over/under-fetching | Cache HTTP não funciona (tudo é POST /graphql) |
| Um endpoint, schema tipado | N+1 nos resolvers |
| Evolução sem versionar | Complexidade de servidor bem maior |
| Introspecção e tooling | Query maliciosa pode derrubar o servidor |
Os três problemas sérios, em ordem de importância prática:
Cache. Em REST, GET /pedidos/42 é cacheável por qualquer camada da web. Em GraphQL, tudo é POST com corpo variável — nenhuma CDN ou proxy consegue cachear. A saída é cache no cliente por normalização (Apollo, Relay) e persisted queries, que transformam a consulta num hash cacheável.
N+1. Um resolver de itens chamado para cada um dos 10 pedidos gera 10 consultas ao banco. É o Chatty IO em forma de resolver, e a solução padrão é DataLoader — agrupar as chamadas do mesmo tick numa consulta em lote.
Custo de query. Um cliente pode escrever uma consulta profundamente aninhada que faz o servidor executar milhares de resolvers. Defesas: limite de profundidade, análise de custo, timeout e allow-list de queries.
E o custo de observabilidade: com um endpoint só, métricas por status code e por rota deixam de significar algo — a instrumentação precisa ser por campo e por resolver.
Exemplo prático
O mesmo perfil de REST, que exigia três chamadas e trazia 40 campos para usar 3:
query { usuario(id: 42) {
nome
enderecoPadrao { rua cidade }
pedidos(ultimos: 10) { id total }
} }
Uma rodada de rede, zero campo desperdiçado. Num app móvel, é a diferença mais visível que GraphQL entrega.
O que ele cobra em troca: os resolvers de enderecoPadrao e pedidos precisam de DataLoader para não virar N+1, e a resposta não será cacheada por nenhuma CDN. A escolha, portanto, não é "GraphQL é melhor" — é qual dos dois conjuntos de problemas custa menos no seu caso.
Relacionado
Parte de Communication · roadmap.sh/system-design