Retry Policy no desenvolvimento mobile — essência, estratégias e princípios

Autor: IT Sectr Publicado: 2026-03-11 Tempo de leitura: 10 min

Retry Policy — política de repetição de requisições — é um conjunto de regras que determinam quando e como um aplicativo móvel repete automaticamente chamadas de rede com falha. Com conexões instáveis ou erros temporários do servidor, uma política de repetição bem projetada melhora a confiabilidade do aplicativo sem intervenção do usuário. De acordo com uma pesquisa do Google Developer Relations (2025), a implementação correta da Retry Policy reduz a porcentagem de requisições perdidas em 40–60% em aplicativos móveis com operações de rede frequentes.

Pontos principais

  • Retry Policy é uma estratégia de repetição automática de requisições durante falhas de rede ou erros temporários do servidor.
  • Exponential backoff é um método de aumento do atraso entre repetições para reduzir a carga do servidor.
  • Jitter é um desvio aleatório do atraso que previne o efeito de manada (thundering herd).
  • Idempotência é um requisito chave para repetições seguras: uma requisição repetida não deve causar efeitos colaterais.
  • Circuit Breaker é um mecanismo para interromper repetições durante indisponibilidade prolongada do serviço para conservar recursos.

O que é Retry Policy?

Retry Policy é uma estratégia de software que define o comportamento do cliente diante de uma falha de requisição de rede: quais erros devem ser repetidos, quantas vezes, com qual atraso e quando parar de tentar. Em aplicativos móveis, a política de repetição é criticamente importante devido à instabilidade das redes móveis e possíveis falhas temporárias do servidor.

Uma Retry Policy básica inclui três parâmetros: número máximo de repetições (maxRetries), atraso inicial (baseDelay) e a estratégia de backoff. Além disso, pode ser especificada uma lista de códigos de status HTTP que devem acionar uma repetição e um tempo limite para abortar todas as tentativas.

De acordo com o livro “Designing Data-Intensive Applications” de Martin Kleppmann, 50% das falhas em sistemas distribuídos são temporárias e são resolvidas com uma repetição. Isso torna a Retry Policy uma das maneiras mais eficazes e baratas de melhorar a tolerância a falhas de um aplicativo móvel sem alterações na arquitetura do servidor.

Quais erros devem ser repetidos

Erros temporários (retriable) são o único tipo de falha ao qual a Retry Policy deve responder. Estes incluem timeouts de conexão (SocketTimeoutException), indisponibilidade temporária do servidor (HTTP 503, 502) e erros de DNS. Erros permanentes — HTTP 400, 401, 403, 404 — não devem ser repetidos, pois indicam um problema na requisição, não na rede ou servidor.

De acordo com o AWS Architecture Blog, a classificação correta de erros em retriable e non-retriable é a decisão mais importante ao projetar uma Retry Policy. Repetir uma requisição não idempotente com HTTP 401 pode levar ao bloqueio da conta, e repetir HTTP 400 pode criar dados duplicados. Sempre configure explicitamente a lista de códigos para repetição.

Estratégias básicas de repetição

Intervalo fixo é a estratégia mais simples: cada repetição ocorre após o mesmo intervalo de tempo. Por exemplo, com um atraso de 2 segundos, o aplicativo repete a requisição após 2, 2, 2 segundos. O intervalo fixo é simples de implementar e previsível, mas cria uma carga uniforme no servidor durante falhas em massa.

Intervalo incremental — o atraso aumenta linearmente a cada repetição: primeira repetição após 1 segundo, segunda após 2, terceira após 3 e assim por diante. Esta estratégia dá ao servidor mais tempo para se recuperar em falhas repetidas, mas ainda é previsível para muitos clientes falhando simultaneamente.

EstratégiaFórmula de atrasoTempo acumulado (3 tentativas)Aplicação
Fixodelay = D3 × DCenários simples, timeouts locais
Incrementaldelay = N × D6 × DRedução gradual de carga
Exponencialdelay = D × 2^N7 × DFalhas em massa, serviços cloud
Exponencial + Jitterdelay = random(0, D × 2^N)variávelCarga alta, microsserviços

A escolha da estratégia depende da natureza do aplicativo. Para tarefas em segundo plano de sincronização de dados em dispositivos móveis, a estratégia exponencial com jitter é ideal — ela oferece a maior probabilidade de sucesso com carga mínima no servidor e no dispositivo do usuário.

Exponential Backoff e Jitter

Exponential backoff é uma estratégia onde o atraso entre repetições dobra a cada tentativa. Se o atraso inicial é de 1 segundo, a sequência de atrasos será 1, 2, 4, 8, 16 segundos. Isso dá ao servidor um tempo de recuperação exponencialmente crescente.

Jitter é um desvio aleatório do atraso que impede requisições de repetição síncronas de múltiplos clientes (problema de thundering herd). Sem jitter, mil clientes com a mesma Retry Policy repetiriam requisições simultaneamente, criando pico de carga no servidor. O Jitter distribui as repetições no tempo.

Implementação em Kotlin com corrotinas

As corrotinas do Kotlin permitem implementar exponential backoff com jitter sem bloquear a thread principal. A função retry do kotlinx-coroutines aceita uma condição de repetição e um bloco com o corpo da requisição, gerenciando automaticamente atrasos e número de tentativas.

kotlin
suspend fun RetryPolicy.executeWithRetry(
    block: suspend () -> Result<T>
): Result<T> {
    var lastError: Throwable? = null
    repeat(maxRetries + 1) { attempt ->
        try {
            return block()
        } catch (e: Exception) {
            if (!isRetriable(e) || attempt == maxRetries) {
                return Result.failure(e)
            }
            val delay = (baseDelayMs * (1 shl attempt))
                .toLong()
            val jitteredDelay = (delay * (0.5 + Random.nextDouble())).toLong()
            delay(jitteredDelay)
            lastError = e
        }
    }
    return Result.failure(lastError!!)
}

A função executeWithRetry recebe uma lambda com uma chamada de rede e a executa com exponential backoff e jitter. Se o erro não for retriable ou o número máximo de tentativas for excedido, a função retorna um erro. O atraso é multiplicado por um fator aleatório de 0.5 a 1.5 para distribuição uniforme das repetições.

Circuit Breaker e interrupção de repetições

Circuit Breaker é um padrão de projeto que evita requisições de repetição infinitas durante indisponibilidade prolongada do serviço. Quando o número de erros excede um limite, o Circuit Breaker transiciona para o estado OPEN e retorna imediatamente um erro sem executar a requisição, dando ao servidor tempo para se recuperar.

Em aplicativos móveis, o Circuit Breaker é especialmente útil quando uma API está indisponível devido a manutenção programada ou falhas de rede da operadora. Sem ele, o aplicativo consumiria bateria e tráfego em tentativas de repetição infinitas, degradando a experiência do usuário e reduzindo a autonomia do dispositivo.

Máquina de estados do Circuit Breaker

O Circuit Breaker tem três estados: CLOSED (operação normal, requisições são executadas), OPEN (falha, requisições são bloqueadas) e HALF_OPEN (requisição de teste para verificar recuperação). Após um tempo limite no estado OPEN, o disjuntor transiciona para HALF_OPEN e executa uma requisição — em caso de sucesso retorna para CLOSED, em caso de falha para OPEN.

kotlin
class CircuitBreaker(
    private val failureThreshold: Int = 3,
    private val timeoutMs: Long = 30000
) {
    private var state = State.CLOSED
    private var failureCount = 0
    private var lastFailureTime: Long = 0

    suspend fun T.protect(block: suspend () -> T): T {
        checkState()
        return try {
            val result = block()
            onSuccess()
            result
        } catch (e: Exception) {
            onFailure()
            throw e
        }
    }
}

A implementação do Circuit Breaker em Kotlin contém um contador de erros e um timer de recuperação. O método protect verifica o estado atual antes de executar a requisição encapsulada e atualiza o contador de erros em falhas. Após atingir o failureThreshold, todas as requisições são imediatamente rejeitadas até que o timeoutMs expire.

Retry Policy em aplicativos móveis

As redes móveis têm características que tornam a Retry Policy especialmente importante. Alternância entre Wi-Fi e dados móveis, perda de sinal em metrôs e túneis, bloqueios temporários a nível de operadora — todos esses cenários levam a falhas de requisição que podem ser tratadas com sucesso por repetições.

No Android, a biblioteca Retrofit e OkHttp fornecem um mecanismo de repetição integrado através do Interceptor. No iOS, a tarefa é resolvida via URLSessionConfiguration e delegação personalizada. Para desenvolvimento multiplataforma, o Ktor (KMP) inclui suporte integrado a repetição com estratégias configuráveis.

Implementação no iOS com Combine

Combine é o framework da Apple para programação reativa. O operador retry no Combine repete o publisher um número especificado de vezes ao ocorrer erro, mas não permite configurar o atraso entre repetições. Para uma Retry Policy completa, é usada uma combinação personalizada de catch e flatMap com atraso.

swift
extension Publisher {
    func retryWithBackoff(
        retries: Int = 3,
        baseDelay: TimeInterval = 1.0
    ) -> AnyPublisher<Output, Failure> {
        return self.catch { error -> AnyPublisher in
            guard retries > 0 else {
                return Fail(error).eraseToAnyPublisher()
            }
            return Just(())
                .delay(for: .seconds(baseDelay), scheduler: DispatchQueue.main)
                .flatMap { self.retryWithBackoff(
                    retries: retries - 1,
                    baseDelay: baseDelay * 2
                ) }
                .eraseToAnyPublisher()
        }
        .eraseToAnyPublisher()
    }
}

A extensão retryWithBackoff para Publisher no Combine implementa exponential backoff através de chamadas recursivas com contador decrescente e atraso dobrado. O operador delay cria uma pausa entre repetições, enquanto catch intercepta o erro e decide se deve repetir ou retornar falha.

Erros comuns na Retry Policy

O primeiro erro — repetir requisições sem verificar idempotência. Se o servidor criou um recurso mas não retornou confirmação devido a uma falha de rede, uma repetição criará um duplicata. Para requisições POST, sempre use uma chave de idempotência (Idempotency-Key) no cabeçalho ou limite as repetições apenas para GET, PUT e DELETE.

O segundo erro — repetir infinitamente. Sempre defina um número máximo de tentativas (3–5 para aplicativos móveis) e um tempo limite total para todas as tentativas. Repetições infinitas drenam a bateria e criam carga parasitária no servidor, especialmente durante migrações de banco de dados ou mudanças de API.

O terceiro erro — ignorar o contexto do aplicativo. Se o usuário fechou o aplicativo ou entrou em segundo plano, as Retry Policies ativas devem ser canceladas corretamente. Use corrotinas com SupervisorScope ou Combine com ciclo de vida da UI para cancelamento automático de repetições ao fechar a tela.

O quarto erro — não registrar as tentativas de repetição. Sem registro, você não saberá quantas requisições foram repetidas, quais erros ocorreram e quão eficaz é sua Retry Policy. Adicione métricas: número de repetições, sucesso após repetição, distribuição de atrasos. Esses dados ajudarão a ajustar os parâmetros ideais da estratégia para seu aplicativo específico.

Perguntas frequentes

Quantas vezes repetir uma requisição em um aplicativo móvel?

O número ideal de repetições é de 3 a 5 tentativas para a maioria dos cenários. Para sincronização em segundo plano, 5 a 7 tentativas são aceitáveis; para requisições interativas (como envio de formulário), no máximo 3. Um número maior de repetições não aumenta a probabilidade de sucesso, mas consome a bateria e o tráfego de dados do usuário.

O que é exponential backoff em termos simples?

Exponential backoff é a duplicação do atraso entre tentativas de repetição: 1 segundo, 2, 4, 8, 16 e assim por diante. Se o servidor está sobrecarregado, a pausa curta entre as primeiras repetições permite que ele responda rapidamente, enquanto a pausa crescente a cada repetição subsequente dá ao servidor mais tempo para se recuperar.

Quais códigos de status HTTP devem ser repetidos?

Repita apenas erros temporários: 408 (Request Timeout), 429 (Too Many Requests), 502 (Bad Gateway), 503 (Service Unavailable), 504 (Gateway Timeout). Erros 4xx (exceto 408 e 429) indicam problemas do cliente — repeti-los não faz sentido e pode ser perigoso para os dados do usuário.

Qual a diferença entre Retry Policy e Circuit Breaker?

Retry Policy gerencia a repetição de uma única requisição em caso de falha. O Circuit Breaker gerencia o estado da conexão com um serviço: quando erros se acumulam, ele abre o circuito (OPEN) e bloqueia novas requisições. A repetição funciona no nível da chamada individual, o Circuit Breaker no nível da integração com o serviço.

Como testar a Retry Policy em dispositivos móveis?

Para testar a Retry Policy, use NetworkInterceptor (OkHttp) no Android e URLProtocol (URLSession) no iOS para simular falhas de rede. Configure parâmetros: frequência de erros, duração da indisponibilidade e códigos de resposta. Testes unitários com MockWebServer (OkHttp) ou OHHTTPStubs (iOS) verificam a lógica de repetição sem rede real.

Resumo

  • Retry Policy é uma estratégia de repetição automática de requisições de rede durante falhas temporárias com parâmetros configuráveis de atraso e número de tentativas.
  • Exponential backoff com jitter é a estratégia básica para aplicativos móveis, reduzindo a carga do servidor durante falhas em massa e prevenindo o efeito thundering herd.
  • Idempotência é uma condição obrigatória para repetir com segurança requisições não-GET: sem ela, uma repetição cria dados duplicados ou efeitos colaterais indesejados.
  • Circuit Breaker complementa a Retry Policy prevenindo repetições infinitas durante indisponibilidade prolongada do serviço e conservando recursos do dispositivo.
  • Classificação de erros em retriable (503, 502, timeout) e non-retriable (400, 401, 403) é criticamente importante para a operação correta da política de repetição.
  • Máximo 3–5 repetições em cenários interativos e até 7 para sincronização em segundo plano é o valor ideal para aplicativos móveis segundo o Google Developer Relations.
  • Recomendação — implemente Retry Policy com exponential backoff, Circuit Breaker e registro para todas as requisições de rede em aplicativos móveis.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também