Rate limiting e throttling em Swift: proteção e otimização de API

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Sua API sob ataque: por que rate limiting e throttling são must have para desenvolvedores Swift

\n\n

Imagine: você lançou um aplicativo incrível em Swift, os usuários estão encantados, os servidores funcionam perfeitamente. Mas de repente — colapso. Alguém executou um script que sobrecarrega sua API com milhares de requisições por segundo. Ou apenas um usuário ativo fica spamando o botão "Atualizar" mais rápido do que você consegue processar os dados. Resultado — lentidão, queda do servidor e avaliações negativas.

\n\n

Familiar? Então este artigo é para você. Vamos abordar rate limiting e throttling em Swift — técnicas que salvarão seu backend e tornarão o aplicativo estável. Você aprenderá como implementar a limitação de requisições em Swift no lado do cliente, usando abordagens modernas com async/await, e quais padrões realmente funcionam.

\n\n

Rate limiting vs Throttling: qual a diferença?

\n\n

Antes de escrever código, vamos esclarecer os termos. Muitos confundem esses conceitos, embora eles resolvam problemas diferentes.

\n\n

Rate limiting (limitação de velocidade)

\n

É um limite rígido: "No máximo N requisições por período". Se o limite for excedido — a requisição é rejeitada. O servidor geralmente retorna 429 Too Many Requests. Exemplo: você permite no máximo 100 requisições por minuto de um único IP.

\n\n

Throttling (estrangulamento)

\n

É um mecanismo mais suave: as requisições não são bloqueadas, mas colocadas em uma fila e executadas em uma frequência definida. Imagine que sua API pode processar apenas 5 requisições por segundo. O throttling as colocará em fila e as enviará na velocidade necessária, sem sobrecarregar o servidor.

\n\n

Em Swift, ambas as abordagens são implementadas de forma diferente. Vamos analisar as melhores práticas.

\n\n

Implementações práticas de rate limiting em Swift

\n\n

1. Throttling simples com timer (GCD)

\n\n

A maneira mais simples de limitar requisições em Swift é usar DispatchQueue e um timer. Aqui está um exemplo que garante que as requisições sejam enviadas no máximo uma vez por segundo:

\n\n
import Foundation\n\nfinal class RequestThrottler {\n    private let queue = DispatchQueue(label: "com.app.throttle")\n    private var lastRequestTime: Date = .distantPast\n    private let minimumInterval: TimeInterval\n    \n    init(interval: TimeInterval = 1.0) {\n        self.minimumInterval = interval\n    }\n    \n    func performThrottledRequest(block: @escaping () -> Void) {\n        queue.sync {\n            let now = Date()\n            if now.timeIntervalSince(lastRequestTime) >= minimumInterval {\n                lastRequestTime = now\n                DispatchQueue.main.async {\n                    block()\n                }\n            } else {\n                print("Requisição rejeitada: muito frequente")\n            }\n        }\n    }\n}\n\n// Uso\nlet throttler = RequestThrottler(interval: 2.0)\nthrottler.performThrottledRequest {\n    // Sua requisição de API\n    print("Requisição executada")\n}
\n\n

Essa abordagem é simples, mas não é ideal: ela simplesmente descarta requisições "excedentes". Para muitos cenários, isso é suficiente, mas se você precisar preservar a ordem e garantir a execução — continue lendo.

\n\n

2. Rate limiter com fila (async/await)

\n\n

Com o advento do Swift async/await, ganhamos uma maneira elegante de implementar um swift rate limiter com suporte a fila. Veja como fica:

\n\n
import Foundation\n\nactor RateLimiter {\n    private let maxRequests: Int\n    private let perSecond: Double\n    private var requestTimestamps: [Date] = []\n    private var pendingTasks: [CheckedContinuation] = []\n    private var isProcessing = false\n    \n    init(maxRequests: Int, perSecond: Double) {\n        self.maxRequests = maxRequests\n        self.perSecond = perSecond\n    }\n    \n    func waitForSlot() async throws {\n        try await withCheckedThrowingContinuation { continuation in\n            pendingTasks.append(continuation)\n            if                

Blogs

Book Recommendations