15 de dez. de 2025·7 min de leitura

Design de API para bateria móvel: reduzir a comunicação excessiva

Design de API para bateria móvel: aprenda batching, cabeçalhos de cache e redução de payloads para diminuir acordadas do rádio, acelerar telas e reduzir consumo.

Design de API para bateria móvel: reduzir a comunicação excessiva

Por que APIs “conversadoras” drenam a bateria no mobile

Uma API “conversadora” faz o app disparar muitas requisições pequenas para montar uma única tela. Cada requisição parece barata no papel, mas no celular elas somam rápido.

O maior impacto na bateria costuma vir do rádio de rede. Os chips de celular e Wi‑Fi entram em estados de alta potência para enviar e receber dados. Quando um app faz muitas requisições próximas no tempo, o rádio fica acordando e ativo por mais tempo. Mesmo que cada resposta seja pequena, acordadas repetidas consomem energia real.

Há trabalho de CPU também. Cada requisição significa montar headers, fazer trabalho TLS, parsear JSON, atualizar caches e rodar código do app para mesclar resultados. Se conexões caem, o trabalho de setup se repete.

A conversação excessiva também deixa a interface mais lenta. Em vez de um carregamento previsível, a tela espera por uma cadeia de chamadas. Você vê spinners mais longos, renderizações parciais que pulam e mais timeouts quando a rede está fraca. O refresh em background piora da mesma forma: mais retries, mais wakeups, mais drenagem de bateria.

Uma forma prática de pensar sobre design de API para bateria móvel é simples: mostrar a mesma interface com menos viagens de ida e volta, menos bytes e menos trabalho em background.

Você pode acompanhar o sucesso com algumas mudanças concretas:

  • Menos chamadas de API por carregamento de tela
  • Menos bytes baixados por tela
  • Melhor tempo mediano e pior caso para ficar interativo em celular
  • Menos fetches em background e menos retries para o mesmo resultado

Quando isso melhora, a responsividade e a duração da bateria geralmente melhoram juntas.

O que medir antes de mudar qualquer coisa

Antes de agrupar requisições ou ajustar cache, tenha uma foto clara do que o app faz hoje. As vitórias rápidas costumam vir de consertar alguns culpados recorrentes, mas você só os encontra se medir telas e fluxos reais (não apenas um teste de caminho feliz).

Para um punhado de telas de alto tráfego, registre o básico: quantas requisições ocorrem por carregamento, quais endpoints são chamados, bytes enviados e recebidos (headers mais corpo), taxas de retry e timeout, e quanto tempo leva até a UI ficar utilizável. Se possível, separe taxas de erro por tipo de rede (Wi‑Fi vs celular). Essas divisões frequentemente revelam problemas que você perderia em uma conexão estável.

Separe tráfego em primeiro plano do background. Uma tela pode parecer silenciosa, mas o telefone pode estar ocupado com refresh em background, sincronizações acionadas por push, uploads de analytics ou prefetch “por segurança”. Meça esses separadamente para não otimizar a coisa errada.

Os pontos quentes tendem a se agrupar em alguns momentos: abertura do app, tela inicial/feed, telas de detalhe que disparam várias chamadas e pull-to-refresh. Escolha uma dessas e meça de ponta a ponta.

Defina um orçamento base para que a equipe concorde sobre o que é “bom”. Por exemplo: “Um cold load da tela de rastreamento de pedido não deve fazer mais que 6 requisições e baixar mais que 250 KB antes de mostrar o status.”

Se quiser um par de KPIs simples para começar, use (1) requisições por carregamento de tela e (2) taxa de retry. Cortar retries costuma economizar mais bateria do que o esperado, porque retries repetidos mantêm o rádio ativo por mais tempo.

Passo a passo: reduzir requisições com batching

APIs conversadoras são fáceis de criar por acidente. Cada widget carrega “seus” dados, e uma tela dispara uma dúzia de chamadas pequenas. A correção geralmente não é complicada: identifique o que sempre carrega junto e retorne isso em menos chamadas.

Comece mapeando uma tela de alto tráfego (início, inbox, lista de pedidos). Anote o que aparece acima da dobra e trace cada elemento de UI até a requisição que o alimenta. Frequentemente você encontrará duplicatas (o mesmo perfil de usuário buscado duas vezes) e chamadas que sempre viajam juntas (perfil mais permissões mais contador de não lidos).

Em seguida, agrupe chamadas que acontecem de forma confiável juntas. Geralmente há duas opções:

  • Criar um endpoint feito para aquela tela (frequentemente o mais estável)
  • Adicionar um endpoint de batch que aceita uma pequena lista previsível de recursos

Mantenha batches orientados à tela e limitados para que sejam fáceis de cachear, monitorar e depurar.

Algumas regras evitam que o batching vire bagunça. Retorne apenas o que a tela precisa agora, não objetos completos “só por precaução”. Se alguns pedaços são opcionais, deixe isso explícito para que a UI renda as partes importantes rapidamente. Também projete a resposta para que falhas parciais não forcem um retry completo. É muito mais barato re-tentar só o que falhou do que reenviar o batch inteiro.

Cabeçalhos de cache que salvam bateria (não só banda)

Cache é um recurso de bateria. Toda requisição acorda o rádio, mantém a CPU ocupada e dispara parsing e lógica do app. Bons cabeçalhos de cache transformam muitos refreshes em checagens leves.

O maior ganho é com requisições condicionais. Em vez de rebaixar os mesmos dados, o app pergunta “isso mudou?” Se não, o servidor responde com um pequeno 304 Not Modified.

Use ETag em respostas que representam uma versão de um recurso, e faça o cliente enviar If-None-Match no próximo fetch. Se gerar um ETag for difícil, Last-Modified com If-Modified-Since funciona bem para recursos simples com “updated at”.

Para dados que mudam raramente, deixe a decisão de cache explícita. Cache-Control deve refletir a realidade. Um max-age curto para perfis de usuário pode ser aceitável, enquanto config do app, listas de referência e feature flags podem ter prazo maior.

No lado do app, trate 304 como um caminho rápido. Não parseie JSON (não há), não reconstrua modelos e não pisque a UI. Mantenha o que já está na tela e apenas atualize indicadores.

Exemplo: uma tela de rastreamento de pedido faz polling do status a cada 15 segundos. Se a resposta inclui um ETag, a maior parte das checagens pode retornar 304. O app guarda o último status e só faz trabalho real quando o status muda (por exemplo, “Packed” para “Shipped”).

Seja intencional com dados sensíveis. Cache não é automaticamente inseguro, mas precisa de regras claras. Evite cachear respostas com dados pessoais ou tokens a menos que requisitos de produto permitam. Use vidas curtas para dados específicos do usuário e impeça caches compartilhados de armazenarem respostas privadas (use Cache-Control: private quando necessário).

Payloads mais inteligentes: envie menos, parseie menos

Transforme planos de API em código
Modele seus dados e gere código de backend real sem escrever boilerplate.
Começar a construir

Cada byte extra custa mais que a banda no mobile. Mantém o rádio acordado por mais tempo e faz o app gastar CPU decodificando JSON e atualizando modelos. Se você quer reduzir a comunicação excessiva da API, aparar payloads costuma ser a vitória mais rápida.

Comece auditando payloads por tela. Escolha uma tela (por exemplo, o feed inicial), registre tamanhos de resposta e analise campo a campo: o cliente renderiza isso ou usa para decidir o que mostrar? Se não, remova desse endpoint.

Para listas, uma forma de “resumo” normalmente basta. Uma linha de lista geralmente precisa de id, título, status e um timestamp. Não precisa de descrições completas, notas longas ou objetos profundamente aninhados. Busque detalhes apenas quando o usuário abrir um item.

Algumas mudanças frequentes cortam payloads rapidamente:

  • Prefira ids ou códigos enum curtos em vez de strings longas repetidas
  • Não reenvie defaults óbvios que o cliente pode assumir com segurança
  • Evite repetir o mesmo objeto aninhado em cada item da lista
  • Mantenha nomes de campos e tipos estáveis para que o cliente não faça ramificações e re-parse desnecessário

Compressão pode ajudar, especialmente em redes lentas, mas teste o tradeoff de CPU em dispositivos reais. Gzip ou Brotli costumam reduzir muito o tamanho transferido, mas aparelhos mais antigos podem gastar tempo perceptível descomprimindo respostas muito grandes. O melhor ganho continua sendo enviar menos dados desde o começo.

Trate formatos de resposta como um contrato. Quando nomes de campo e tipos ficam consistentes, o app precisa de menos fallback e menos código defensivo, o que ajuda a manter a UI suave e o consumo de bateria baixo.

Projetar para redes ruins e menos retries

Um app móvel não queima bateria apenas quando envia requisições. Também gasta quando falha, re-tenta, acorda o rádio de novo e repete trabalho. Se uma API assume Wi‑Fi perfeito, usuários reais em 4G instável pagam por isso.

Facilite pedir menos dados. Prefira filtros e paginação no servidor em vez de “baixe tudo e filtre no telefone”. Se uma tela precisa dos últimos 20 eventos de um usuário, ofereça essa consulta exata para que o app não busque centenas de linhas só para descartar a maioria.

Suporte sync delta para que o app possa perguntar “o que mudou desde a última vez?” Isso pode ser tão simples quanto retornar um timestamp ou número de versão crescente, deixando o cliente pedir apenas updates e deletes desde aquele ponto.

Retries são inevitáveis, então torne atualizações idempotentes. Um retry não deve cobrar em dobro, submeter em dobro ou criar duplicatas. Chaves de idempotência para operações de criação e semântica de atualização que setam estado (em vez de “adicionar um a mais”) ajudam bastante.

Quando retries ocorrem, evite storms. Use backoff exponencial com jitter para que milhares de dispositivos não ataquem seus servidores ao mesmo tempo, e para que o telefone não acorde a cada segundo.

Retorne códigos de erro claros que ajudem o app a decidir o que fazer. Um 401 deve disparar re-autenticação, um 404 normalmente deve parar de re-tentar, um 409 pode exigir refresh de estado, e 429 ou 503 devem acionar backoff.

Comportamentos do cliente que multiplicam custos de API

Comprove o impacto em dias
Comece com uma tela de alto tráfego e entregue uma queda mensurável em requests.
Experimentar AppMaster

Mesmo com uma API bem desenhada, o cliente pode multiplicar silenciosamente o trabalho de rede. No mobile, esses wakeups extras e o tempo do rádio geralmente custam mais bateria que os próprios bytes.

Faça cache de dados que mudam raramente. Fotos de perfil, feature flags e dados de referência (países, status, categorias) não deveriam ser buscados a cada visita de tela. Dê lifetimes sensatos, armazene no disco e atualize só quando necessário. Se a API suporta validação (ETag ou Last-Modified), uma checagem rápida costuma ser muito mais barata que um download completo.

Outro problema comum são requisições duplicadas em voo. Duas partes do app pedem o mesmo recurso ao mesmo tempo (por exemplo, um cabeçalho e uma tela de configurações pedem o perfil). Sem coalescer, você manda duas chamadas, parseia duas respostas e atualiza estado duas vezes. Trate uma chamada de rede como fonte única de verdade e deixe múltiplos consumidores aguardarem por ela.

Refresh em background deve ser intencional. Se não muda o que o usuário vê logo, ou não vai disparar uma notificação, normalmente pode esperar. Evite rodar lógica de refresh em toda reabertura do app. Adicione um cooldown curto e verifique quando os dados foram atualizados pela última vez.

Se você constrói backends com AppMaster, fica mais fácil suportar esses comportamentos do cliente moldando endpoints ao redor de telas, mantendo esquemas de resposta consistentes e adicionando cabeçalhos de cache de forma controlada para que clientes possam ficar quietos na maior parte do tempo.

Erros comuns com batching, cache e payloads

Desenhe um endpoint de tela em lote
Combine o que uma tela precisa em uma resposta limitada que seu app pode cachear.
Criar endpoint

O objetivo é menos wakeups do rádio, menos trabalho de CPU e menos retries. Alguns padrões podem cancelar as economias e até fazer telas parecerem mais lentas.

Quando batching piora as coisas

Batching ajuda até o ponto em que o batch vira uma chamada “me dá tudo”. Se o servidor precisa joinar muitas tabelas, rodar checagens pesadas de permissão e construir uma resposta enorme, essa única requisição pode demorar mais que várias menores. No mobile, uma requisição lenta mantém o app esperando, mantém a rede ativa e aumenta risco de timeout.

Um batch mais saudável é em forma de tela: só o que uma view precisa, com limites claros. Se você não consegue descrever a resposta em uma frase, o endpoint provavelmente está amplo demais.

Cache que cria telas desatualizadas

Cache sem invalidação clara gera um loop ruim: usuários veem dados antigos, fazem pull-to-refresh e o app faz reloads completos extras. Use cabeçalhos de cache com um plano sobre o que atualiza os dados (ações de create/update, eventos do servidor ou janelas curtas de freshenss) para que o cliente possa confiar em respostas cacheadas.

Polling é outra armadilha de bateria. Um timer apertado de 5 segundos mantém o dispositivo ocupado mesmo quando nada muda. Prefira updates acionados por servidor quando possível, ou aplique backoff agressivo (intervalos maiores após polls vazios, pause em background).

Payloads enormes são um custo silencioso. Retornar objetos aninhados gigantes “por conveniência” significa mais bytes, mais parsing JSON e mais churn de memória. Envie apenas o que a tela precisa e busque detalhes sob demanda.

Por fim, não ignore falhas parciais em um batch. Se um sub‑resultado falha e você re-tenta o batch inteiro, duplica tráfego. Projete respostas para que o cliente possa re-tentar apenas as partes que falharam.

Uma checklist mental rápida: mantenha batches limitados, defina freshenss do cache desde o início, evite polling apertado, reduza payloads e suporte sucesso parcial.

Checklist rápido pré-release

Antes de lançar, faça uma passada focada apenas no comportamento de rede. A maioria das economias de bateria vem de remover surpresas: menos wakeups, menos parsing e menos retries em background.

Rode isso nas suas três principais telas:

  • Carregamentos a frio terminam em um número pequeno e previsível de requisições (fique atento a chamadas oculta como lookups por item)
  • Respostas incluem regras de cache claras (ETag ou Last-Modified quando aplicável) e retornam 304 Not Modified quando nada mudou
  • Endpoints de listagem são limitados: ordenação estável, paginação e sem campos não usados por padrão
  • Lógica de retry aplica backoff com jitter e para em erros que não se resolvem sozinhos; tempo total de retries é limitado
  • Atualizações em background são justificadas; evite polling constante a menos que realmente mude o que o usuário vê

Um cheque de realidade simples: carregue uma tela uma vez, ative o modo avião e então reabra. Se ela ainda mostra algo útil (conteúdo em cache, último estado conhecido, placeholders amigáveis), você provavelmente reduziu chamadas desnecessárias e melhorou a velocidade percebida também.

Exemplo: tornar a tela de rastreamento de pedido mais barata de carregar

Entregue APIs móveis mais silenciosas
Construa um backend orientado à tela que carrega com menos chamadas e menos bytes.
Experimentar AppMaster

Um cliente abre um app de rastreamento de pedidos em dados móveis com 20% de bateria. Ele quer uma coisa: “Onde está meu pacote agora?” A tela parece simples, mas o tráfego de API por trás pode ser surpreendentemente caro.

Antes, o app carrega a tela com uma explosão de requisições. A UI espera enquanto o rádio acorda repetidas vezes, e algumas chamadas time-out numa conexão fraca.

Um padrão típico “antes” é:

  • GET /orders/{id} para resumo do pedido
  • GET /orders/{id}/items para itens da linha
  • GET /orders/{id}/history para eventos de status
  • GET /me para perfil e preferências do usuário
  • GET /settings para regras de exibição (moeda, formato de data)

Agora aplique três mudanças que não alteram a UI.

Primeiro, adicione um endpoint de tela único que retorne só o que a view precisa em uma viagem: resumo do pedido, último status, histórico recente e títulos dos itens. Segundo, faça cache do perfil: GET /me retorna um ETag e Cache-Control: private, max-age=86400, então a maioria das aberturas vira um 304 rápido (ou nenhuma requisição se a cópia em cache ainda estiver válida). Terceiro, enxugue o payload: a lista de itens envia apenas id, name, qty e thumbnail_url, não descrições completas ou metadados não usados.

O resultado é menos viagens de ida e volta, menos bytes e menos retries quando a rede oscila. O rádio do telefone fica dormindo com mais frequência, e é aí que estão as economias reais de bateria.

Para o usuário não aparece nada “novo”. A tela é a mesma, mas carrega mais rápido, parece mais responsiva e continua funcionando mesmo quando a conexão está instável.

Próximos passos: um plano prático de rollout (e onde AppMaster pode ajudar)

Se quiser ganhos rápidos, comece pequeno e comprove impacto. Economias de bateria geralmente vêm de menos wakeups do rádio e menos parsing, não de uma grande reescrita.

Três mudanças seguras, mensuráveis e fáceis de reverter:

  • Meça uma tela de ponta a ponta (contagem de requests, bytes totais, tempo até interatividade, taxa de erro e retry)
  • Agrupe as requisições daquela tela em uma ou duas chamadas (mantenha os endpoints antigos por compatibilidade)
  • Adicione suporte a ETag nos seus GETs de maior tráfego para que clientes possam usar If-None-Match e receber 304 Not Modified

Escolha uma feature com uso constante, como uma lista de pedidos ou caixa de mensagens. Lance por trás de um flag no servidor se puder, então compare KPIs do caminho antigo vs novo por alguns dias. Procure por menos requisições por sessão, menos retries e menos bytes baixados por usuário ativo.

Coordene lançamentos de API e app para que clientes mais antigos não quebrem. Uma regra prática: adicione comportamento novo primeiro, migre clientes depois, remova comportamento antigo por último. Se mudar comportamento de cache, seja cuidadoso com dados personalizados e garanta que caches compartilhados não misturem usuários.

Se quiser prototipar e entregar mudanças de backend mais rápido, AppMaster (appmaster.io) pode ajudar a modelar dados visualmente, construir lógica de negócio com editor drag-and-drop e regenerar código pronto para produção conforme os requisitos mudam.

Tente um endpoint em lote mais ETag em uma tela de alto tráfego primeiro. Se os números melhorarem, você saberá exatamente onde investir mais tempo de engenharia.

FAQ

Quantas chamadas de API por tela são “demais” no mobile?

Um bom ponto de partida é definir um orçamento por tela e depois medir sessões reais. Muitas equipes começam com algo como 4–8 requests para um carregamento a frio em celular, e então reduzem quando resolvem os maiores culpados. O número certo é aquele que atinge de forma consistente seu objetivo de tempo até interatividade sem provocar retries ou longos períodos com o rádio ativo.

Batching é sempre melhor do que múltiplos endpoints pequenos?

Batching geralmente ajuda quando várias chamadas ocorrem sempre juntas, mas pode atrapalhar se o batch virar uma chamada lenta ou enorme. Mantenha respostas de batch “em forma de tela” e limitadas para que uma única requisição não vire ponto crítico de falha. Se um endpoint agrupado costuma estourar timeout ou retornar muitos dados não usados, divida-o em algumas chamadas focadas.

Quais cabeçalhos de cache dão a maior economia de bateria?

Comece com ETag mais requisições condicionais usando If-None-Match, pois isso pode transformar muitas atualizações em pequenas respostas 304 Not Modified. Adicione Cache-Control que reflita com que frequência os dados realmente mudam, para que o cliente evite trabalho de rede desnecessário. Se ETag for difícil, Last-Modified com If-Modified-Since é um bom fallback para recursos com carimbo de data de atualização.

Devo usar ETag ou Last-Modified?

Use ETag quando quiser uma verificação de “versão” confiável para um recurso, especialmente quando mudanças não se mapeiam bem para um timestamp. Use Last-Modified quando o servidor tem um tempo claro de atualização e você aceita granularidade por timestamp. Se só puder implementar um, ETag costuma ser a escolha mais precisa para evitar downloads desnecessários.

O que devo medir antes de mudar minha API?

Instrumente por tela e por sessão, não apenas por endpoint. Registre contagem de requests, bytes (headers mais body), retries, timeouts e tempo até interatividade, e separe tráfego em primeiro plano do background para não otimizar o tráfego errado. Geralmente você descobrirá que poucas telas ou fluxos causam a maior parte dos wakeups repetidos.

Como trato falhas parciais em uma resposta em lote?

Projete a resposta do batch para que cada sub‑resultado possa falhar ou suceder independentemente, e inclua detalhes de erro suficientes para o cliente re-tentar apenas o que falhou. Evite obrigar o cliente a re-pedir o lote inteiro só porque uma peça quebrou. Isso reduz tráfego duplicado e previne wakeups extras em conectividade instável.

Qual a forma mais rápida de reduzir o tamanho do payload sem quebrar o app?

Remova campos que a tela não renderiza agora e use formatos de resumo para listas. Mova campos pesados ou raramente usados para um endpoint de detalhe que só é chamado quando o usuário abre um item. Isso reduz bytes pelo ar e também o parsing JSON e atualizações de modelo, que podem representar custo significativo de CPU e bateria em telefones.

Como afinar lógica de retry para economizar bateria?

Use backoff exponencial com jitter e limite a janela total de retries para que o telefone não acorde a cada poucos segundos. Faça operações de escrita idempotentes para que um retry não crie duplicatas ou duplique ações. Também retorne códigos de status claros para que o cliente pare de re-tentar quando o erro não se resolver sozinho.

Como evito drenagem de bateria por polling por atualizações?

Intervalos de polling apertados mantêm o rádio e a CPU ocupados mesmo quando nada muda. Se precisar poll, aumente intervalos quando respostas não mudarem e pause polling em background. Quando possível, troque por atualizações orientadas por eventos para que o app acorde apenas quando houver algo novo a mostrar.

Como o AppMaster pode me ajudar a entregar essas mudanças de API mais rápido?

No AppMaster, você pode criar endpoints orientados a tela e manter esquemas de resposta consistentes, o que facilita batching e modelagem de payloads. Também dá para implementar comportamentos favoráveis a cache adicionando lógica de versionamento e retornando cabeçalhos que suportem requisições condicionais, para que clientes recebam respostas rápidas de “sem mudança”. Uma abordagem prática é começar com uma tela de alto tráfego, criar um endpoint em lote e adicionar ETag nos GETs principais, depois medir a queda em requests e retries.

Fácil de começar
Criar algo espantoso

Experimente o AppMaster com plano gratuito.
Quando estiver pronto, você poderá escolher a assinatura adequada.

Comece