---
term: 'Overfetching & Underfetching'
seoTitle: 'Overfetching e Underfetching: Causas, Custos e Soluções'
headline: 'O que são overfetching e underfetching?'
slug: overfetching-e-underfetching
category: api-realtime
shortDefinition: 'Overfetching é o problema de API em que respostas carregam mais dados do que o cliente precisa; underfetching força requisições extras para obter o bastante.'
relatedTerms:
  - api-payload-optimization
  - n-plus-one-query-problem
  - graphql-vs-rest
  - rest-api
contrastsWith:
  - graphql-vs-rest
aboutTerms:
  - 'Overfetching'
  - 'Underfetching'
faq:
  - question: 'O que é overfetching?'
    answer: 'Uma API retorna mais dados do que o cliente precisa para a tarefa em questão — uma tela de perfil que renderiza três campos recebe quarenta. O desperdício é pago quatro vezes: serialização no servidor, transferência na rede, parsing no cliente e, no mobile, bateria e dados de franquia. Também pode expor campos que nenhum cliente deveria ver.'
  - question: 'O que é underfetching?'
    answer: 'Um único endpoint não retorna dados suficientes para renderizar a tela, então o cliente faz requisições adicionais para montá-la. Cada chamada extra é um round trip completo de rede; quando as chamadas são sequenciais — buscar a lista, depois buscar os detalhes item a item — a latência se compõe no problema de requisições N+1.'
  - question: 'Qual é a diferença entre overfetching e underfetching?'
    answer: 'A direção. Overfetching significa que cada resposta carrega demais — o custo é bytes; underfetching significa que cada resposta carrega de menos — o custo é round trips. Os dois crescem da mesma raiz: formatos de resposta fixos, desenhados uma vez, consumidos por telas com necessidades diferentes. Muitas APIs cometem os dois ao mesmo tempo, na mesma tela.'
  - question: 'O GraphQL resolve overfetching e underfetching?'
    answer: 'Em grande parte, na camada HTTP: selection sets buscam só os campos pedidos e queries aninhadas reúnem dados relacionados em uma requisição. Mas não é automático — clientes que pedem conjuntos generosos de campos recriam o overfetching, e resolvers ingênuos recriam o underfetching contra o banco de dados como N+1 de resolver, que os loaders com batching existem para corrigir.'
  - question: 'Como evitar overfetching em uma API REST?'
    answer: 'Sparse fieldsets são a solução direta: um parâmetro fields (ou select() nos query builders dos SDKs) que projeta só as colunas que a tela renderiza. Paginação limita o tamanho das listas, endpoints sob medida casam respostas com telas reais e compressão encolhe o que sobra — embora comprimir inchaço seja mitigação, não cura.'
  - question: 'Como corrigir underfetching sem migrar para GraphQL?'
    answer: 'Parâmetros de expansão — include ou expand — que embutem objetos relacionados em uma resposta; documentos compostos que enviam um recurso com suas associações; endpoints compostos que agregam as necessidades de uma tela no servidor; e, arquiteturalmente, uma camada backend-for-frontend que faz a montagem perto dos dados, e não através de uma rede móvel.'
  - question: 'Como o problema N+1 se relaciona com underfetching?'
    answer: 'N+1 é underfetching em escala: uma requisição para uma lista de N itens, depois N requisições de acompanhamento para os detalhes de cada um. O mesmo formato recorre em toda camada — clientes HTTP contra endpoints REST, resolvers GraphQL contra o banco, ORMs com lazy loading de relações — e a solução é sempre a mesma ideia: agrupar os N em um.'
  - question: 'Por que overfetching é um risco de segurança?'
    answer: 'Campos que uma tela nunca renderiza ainda cruzam a rede — e qualquer pessoa pode abrir as ferramentas de desenvolvedor e lê-los. Flags internas, endereços de e-mail e dados de custo vazam assim; taxonomias de segurança classificam isso como exposição excessiva de dados, e o princípio do menor privilégio se aplica a corpos de resposta tanto quanto a permissões.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'GraphQL specification — selection sets'
    url: 'https://spec.graphql.org/October2021/#sec-Selection-Sets'
  - name: 'JSON:API specification — sparse fieldsets'
    url: 'https://jsonapi.org/format/#fetching-sparse-fieldsets'
  - name: 'OWASP API Security Top 10'
    url: 'https://owasp.org/API-Security/'
  - name: 'Backends For Frontends pattern — Sam Newman'
    url: 'https://samnewman.io/patterns/architectural/bff/'
cta:
  title: 'Busque exatamente o que a tela precisa'
  text: 'As queries do Back4app aceitam select() e include() em todos os SDKs — sparse fieldsets e relações em um só round trip sem desenhar um único endpoint — mais uma API GraphQL quando os clientes querem moldar as respostas eles mesmos.'
  linkText: 'Comece grátis'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-08-24'
translationKey: overfetching-underfetching
---

**Overfetching é o problema de API em que respostas carregam mais dados do que o cliente precisa; underfetching força requisições extras para obter o bastante.** São os modos de falha gêmeos dos formatos de resposta fixos — um desperdiça bytes, o outro desperdiça round trips — e a maioria das APIs comete os dois na mesma tela: cada resposta gorda demais, e respostas demais.

## Principais pontos

| Pergunta | Resposta |
| --- | --- |
| Overfetching | Demais por resposta — banda, parsing, bateria, exposição |
| Underfetching | De menos por resposta — round trips extras, cascatas, N+1 |
| A causa raiz | Formatos fixos de endpoint encontrando telas com necessidades diferentes |
| Soluções REST | Sparse fieldsets · params include/expand · paginação · endpoints compostos |
| A resposta do GraphQL | Selection sets — com ressalvas honestas na camada de resolvers |

## Uma tela, três formas de buscá-la

Uma lista de posts que renderiza cada título com o nome do autor:

```text
Overfetching                          Underfetching
GET /posts                            GET /posts            (só IDs de autor)
→ 20 posts × 40 campos                GET /users/11  ┐
→ ~160 KB enviados,                   GET /users/12  │  mais 20 chamadas —
  ~6 KB renderizados (96% desperdício)  …            │  a cascata N+1
                                      GET /users/30  ┘

A query moldada
GET /posts?fields=title,summary,author&include=author&limit=20
→ 20 posts × 3 campos + seus autores — um round trip, ~7 KB
```

A mesma query moldada como código de SDK — projeção e relação em uma requisição:

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK
// One shaped query: no overfetch, no underfetch
const query = new Parse.Query('Post');
query.select('title', 'summary', 'author'); // only what the screen renders
query.include('author');                    // related object, same response
query.limit(20);                            // bounded page
const posts = await query.find();
// 1 round trip — not 1 list call + 20 author calls (N+1)
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// One shaped query: no overfetch, no underfetch
final query = QueryBuilder<ParseObject>(ParseObject('Post'))
  ..keysToReturn(['title', 'summary', 'author']) // only what the screen renders
  ..includeObject(['author'])                    // related object, same response
  ..setLimit(20);                                // bounded page
final response = await query.query();
// 1 round trip — not 1 list call + 20 author calls (N+1)
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// One shaped query: no overfetch, no underfetch
let query = Post.query()
  .select("title", "summary", "author") // only what the screen renders
  .include("author")                    // related object, same response
  .limit(20)                            // bounded page
query.find { result in
  // 1 round trip — not 1 list call + 20 author calls (N+1)
  if case .success(let posts) = result { render(posts) }
}
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// One shaped query: no overfetch, no underfetch
val query = ParseQuery.getQuery<ParseObject>("Post")
query.selectKeys(listOf("title", "summary", "author")) // only what the screen renders
query.include("author")                                // related object, same response
query.limit = 20                                       // bounded page
query.findInBackground { posts, e -> if (e == null) render(posts) }
// 1 round trip — not 1 list call + 20 author calls (N+1)
```

## O que é overfetching?

Overfetching é a versão de camada de API do `SELECT *`: o endpoint retorna sua representação fixa completa, independentemente do que o chamador renderiza. Os custos se empilham em camadas. O servidor serializa campos que ninguém lê; a rede os carrega — e é aí que o mobile sofre, já que o tempo de transferência escala com bytes sobre banda limitada e cada kilobyte desnecessário gasta franquia de dados e bateria de rádio; depois o cliente parseia tudo, porque a descompressão acontece antes da renderização e uma resposta inchada é trabalho de parsing inchado mesmo quando a compressão a escondeu na rede.

O custo mais silencioso é a exposição. Um campo de resposta que a UI nunca mostra continua a um clique das ferramentas de desenvolvedor de ser lido — flags internas, e-mails de outros usuários, dados de margem. O [OWASP API Security Top 10](https://owasp.org/API-Security/) rastreia isso como exposição excessiva de dados (broken object property level authorization): o menor privilégio se aplica a corpos de resposta, e um campo que nenhum cliente deveria ver não deveria nem ser serializado.

## O que é underfetching?

Underfetching é a deficiência oposta: o formato fixo do endpoint carrega de menos, então o cliente vira um integrador — busca a lista, depois o autor de cada item, depois talvez o avatar de cada autor. Cada chamada extra é um round trip completo, e round trips são a moeda de que as redes móveis são mais pobres: a uns realistas 100 ms por requisição, uma lista de 20 itens resolvida sequencialmente gasta dois segundos *só de latência*, antes de qualquer conta de payload.

Em escala, essa cascata tem nome — o [problema de requisições N+1](/glossary/pt/problema-n-mais-1/): uma chamada para N itens, N chamadas para seus detalhes. O formato é fractal; recorre onde quer que uma interface fixa encontre dados relacionais — clientes HTTP contra endpoints REST, resolvers GraphQL contra o banco de dados, ORMs abrindo caminho com lazy loading dentro de um loop — e a cura é sempre alguma forma de agrupar os N em um.

```mermaid
flowchart LR
  accTitle: Cascata de underfetching versus uma query moldada
  accDescr: Com underfetching, o cliente faz uma requisição para uma lista e depois uma requisição sequencial por item, multiplicando a latência de round trips. Uma query moldada retorna a lista com seus dados relacionados em um único round trip.
  subgraph W["Underfetching: 1 + N round trips"]
    L["GET /posts"] --> U1["GET /users/11"] --> U2["GET /users/12"] --> U3["… × 20"]
  end
  subgraph S["Moldada: 1 round trip"]
    Q["GET /posts?fields=…&include=author"]
  end
```

## Overfetching vs. underfetching

| | Overfetching | Underfetching |
| --- | --- | --- |
| Sintoma | Respostas cheias de campos não renderizados | Telas montadas a partir de muitas chamadas |
| Unidade de desperdício | Bytes (e tempo de parsing) | Round trips (e latência) |
| Pior em | Redes de franquia, lentas, limitadas por bateria | Redes de alta latência — cascatas se compõem |
| Detecção | Compare campos retornados vs. campos renderizados | Conte requisições por tela na aba de rede |
| Solução direta | Sparse fieldsets / projeção | Params de expansão, endpoints compostos |
| Escalada | Exposição excessiva de dados (segurança) | Tempestades de requisições N+1 (escala) |

O diagnóstico é misericordiosamente mecânico, e nenhum explainer de ranking diz isso: abra a aba de rede em uma tela. Muitas requisições para uma view é underfetching; respostas grandes cujos campos você não encontra na UI é overfetching. Analytics de endpoint generalizam a auditoria — tamanho de payload p95 por endpoint, requisições por sessão por tela.

## Corrigindo os dois sem sair do REST

A migração para GraphQL não é o primeiro recurso; convenções REST maduras cobrem a maior parte da distância:

- **Sparse fieldsets** — um parâmetro `fields` que projeta a representação: padronizado como [sparse fieldsets do JSON:API](https://jsonapi.org/format/#fetching-sparse-fieldsets), espelhado por opções de query no estilo `$select` e pelos builders `select()` dos SDKs. A solução do overfetching na origem.
- **Parâmetros de expansão** — `include=author,comments` embute recursos relacionados na mesma resposta (documentos compostos), convertendo uma cascata N+1 em uma requisição. A solução do underfetching na origem.
- **Paginação** — limita a dimensão de lista do overfetching; coleções sem limite são bugs de payload que crescem com a adoção.
- **Endpoints sob medida e compostos** — quando uma tela sempre precisa do mesmo agregado, dê a ela um endpoint que retorna exatamente esse agregado, montado no servidor, onde a latência entre serviços é de microssegundos, não de round trips móveis.
- **Um backend-for-frontend** — a versão arquitetural do mesmo movimento: uma camada fina por cliente que fala com APIs internas generosas e serve a cada frontend exatamente o seu formato ([o padrão BFF de Sam Newman](https://samnewman.io/patterns/architectural/bff/)).
- **Compressão** — honesto último lugar: encolhe a transmissão, não o desperdício; custo de parsing e exposição sobrevivem intactos.

## O GraphQL resolve o problema?

Em grande parte — e o "em grande parte" vale a pena conhecer. [Selection sets](https://spec.graphql.org/October2021/#sec-Selection-Sets) tornam a lista de campos do cliente *a própria requisição*, o que aposenta o overfetching clássico, e queries aninhadas montam dados relacionados em um round trip, o que aposenta o underfetching clássico. É exatamente por isso que o debate [GraphQL vs. REST](/glossary/pt/graphql-vs-rest/) começa com essas duas palavras.

As ressalvas moram uma camada abaixo. Clientes que copiam e colam queries generosas overfetcham por hábito — nada garante que uma query casa com o que um componente renderiza, a menos que o time adote fragments por componente. E uma cadeia ingênua de resolvers *underfetcha contra o banco de dados*: uma query de 20 posts com autores vira 1 + 20 leituras no banco, a menos que os resolvers agrupem através de uma camada de loading — o mesmo N+1, realocado. O GraphQL move o problema para uma camada que você controla, o que é progresso genuíno; ele não o apaga.

## Casos de uso comuns

Onde os dois problemas (e suas soluções) aparecem primeiro:

- **Telas de lista no mobile** — o overfetch canônico: linhas completas enviadas para renderizar três campos por célula.
- **Telas de detalhe com relações** — post + autor + comentários: cascatas de underfetch, a menos que expandidas ou compostas.
- **Mercados de rede lenta** — os dois problemas taxados na alíquota máxima; queries moldadas como acessibilidade.
- **Dashboards** — telas agregadas que ou overfetcham linhas brutas ou underfetcham através de cinco serviços; território de BFF.
- **APIs públicas com consumidores diversos** — um formato fixo não serve um mostrador de relógio e um console admin; parâmetros de projeção e expansão deixam cada chamador ajustar.

## Qual problema você tem? Matriz de decisão

| Evidência na aba de rede | Diagnóstico | Primeira solução |
| --- | --- | --- |
| Uma requisição, resposta grande, poucos campos renderizados | Overfetching | Sparse fieldsets / `select()` |
| Muitas requisições sequenciais por tela | Underfetching | `include` / params de expansão |
| Requisições escalam com o tamanho da lista | N+1 | Batch: expansão ou endpoint composto |
| Grandes e muitas ao mesmo tempo | Os dois — comum | Query moldada ou seleção GraphQL |
| Campos de resposta que você preferiria que não saíssem do servidor | Exposição | Apare a serialização no servidor, não no cliente |

## Limitações e trade-offs

- **Projeção acopla clientes a listas de campos.** Um param `fields` que deriva da UI causa bugs de dados faltantes; tipos gerados e review mantêm as seleções honestas.
- **Expansão pode corrigir demais.** `include=comments` em uma lista quente pode enviar megabytes de relações embutidas — respostas expandidas precisam de paginação e limites de profundidade próprios.
- **Endpoints sob medida se multiplicam.** Endpoints por tela consertam a busca e criam uma conta de manutenção de proliferação de endpoints; BFFs concentram essa proliferação em uma camada com dono, ao custo de operá-la.
- **Flexibilidade no servidor tem preço.** Projeção e expansão arbitrárias complicam o cache (cada formato é uma chave de cache) e a autorização (toda combinação precisa ser segura de servir).
- **Os problemas também são sinais de modelagem.** Uma tela que precisa de cortes profundos ou cinco includes pode estar dizendo que os formatos dos recursos estão errados — às vezes a solução é [o modelo de dados](/glossary/pt/modelagem-de-dados/), não a busca.

## Overfetching e underfetching no Back4app

O Back4app é uma plataforma open-source de Backend as a Service (BaaS) que combina banco de dados gerenciado, APIs REST e GraphQL geradas automaticamente, autenticação, armazenamento de arquivos e funções serverless com Cloud Code. As duas soluções vêm como primitivos de query em todos os SDKs — as abas de código acima são o padrão inteiro: `select()` é o sparse fieldset, `include()` é o parâmetro de expansão, e juntos transformam uma cascata 1 + N em um round trip moldado contra a [API REST](/glossary/pt/api-rest/) gerada automaticamente. Quando os clientes querem controle total do formato da resposta, os mesmos dados são consultáveis via selection sets do GraphQL; quando uma tela precisa de um agregado no servidor, uma função de Cloud Code é um endpoint composto que você escreve em um arquivo. A busca casa com a tela — por idioma, não por redesenho de endpoints.
