Votre API sous attaque : pourquoi le rate limiting et le throttling sont indispensables pour le développeur Swift
\n\nImaginez : vous avez lancé une superbe application en Swift, les utilisateurs sont ravis, les serveurs fonctionnent parfaitement. Mais soudainement, l'effondrement. Quelqu'un a lancé un script qui bombarde votre API avec des milliers de requêtes par seconde. Ou simplement un utilisateur actif spamme le bouton « Actualiser » plus vite que vous ne pouvez traiter les données. Résultat : des ralentissements, un crash du serveur et des avis négatifs.
\n\nCela vous parle ? Alors cet article est pour vous. Nous allons détailler le rate limiting et le throttling en Swift — des techniques qui sauveront votre backend et rendront votre application stable. Vous apprendrez comment implémenter la limitation des requêtes en Swift côté client, en utilisant des approches modernes avec async/await, et quels patterns fonctionnent réellement.
\n\nRate limiting vs Throttling : quelle est la différence ?
\n\nAvant d'écrire du code, clarifions les termes. Beaucoup confondent ces concepts, bien qu'ils résolvent des problèmes différents.
\n\nRate limiting (limitation de débit)
\nIl s'agit d'une limite stricte : « Pas plus de N requêtes par période ». Si la limite est dépassée, la requête est rejetée. Le serveur renvoie généralement un 429 Too Many Requests. Exemple : vous autorisez au maximum 100 requêtes par minute depuis une même adresse IP.
Throttling (étranglement)
\nC'est un mécanisme plus souple : les requêtes ne sont pas bloquées, mais mises en file d'attente et exécutées à une fréquence définie. Imaginez que votre API ne peut traiter que 5 requêtes par seconde. Le throttling les mettra en file d'attente et les enverra à la vitesse appropriée, sans surcharger le serveur.
\n\nEn Swift, les deux approches s'implémentent différemment. Examinons les meilleures pratiques.
\n\nImplémentations pratiques du rate limiting en Swift
\n\n1. Throttling simple avec timer (GCD)
\n\nLa façon la plus simple de limiter les requêtes en Swift est d'utiliser DispatchQueue et un timer. Voici un exemple qui garantit que les requêtes ne seront pas envoyées plus d'une fois par seconde :
\n\nimport 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("Requête rejetée : trop fréquente")\n }\n }\n }\n}\n\n// Utilisation\nlet throttler = RequestThrottler(interval: 2.0)\nthrottler.performThrottledRequest {\n // Votre requête API\n print("Requête exécutée")\n}\n\nCette approche est simple, mais pas idéale : elle rejette simplement les requêtes « en trop ». Pour de nombreux scénarios, cela suffit, mais si vous devez préserver l'ordre et garantir l'exécution, lisez la suite.
\n\n2. Rate limiter avec file d'attente (async/await)
\n\nAvec l'arrivée de Swift async/await, nous avons une manière élégante d'implémenter un swift rate limiter avec support de file d'attente. Voici à quoi cela ressemble :
\n\nimport 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