Aller au contenu principal

Patterns

Retry avec backoff exponentiel et jitter

Algorithme initial=1s × 2^attempt ± 10% jitter, max 60s

Le retry naïf (intervalles fixes) crée des thundering herds : à la reprise d'un service, tous les clients retentent en même temps et le re-saturent. Le backoff exponentiel avec jitter étale les retries dans le temps. Algorithme Scell.io pour les webhooks et appels SuperPDP : `delay = min(initial × 2^attempt, max) × (1 + random(-jitter, +jitter))` avec `initial=1s`, `multiplier=2`, `max=60s`, `jitter=0.1`. Sur 5 tentatives, les délais sont approximativement : 1s, 2s, 4s, 8s, 16s (± 10%). Total ~31s pour atteindre l'épuisement, contre 5 retries instantanés qui surchargent. Le jitter est crucial : sans lui, les clients reformeraient des vagues synchrones. À implémenter côté client (SDK) ET côté serveur (worker queue).

À retenir

  • Formule : delay = min(initial × 2^n, max) × (1 + jitter)
  • Valeurs Scell.io : initial=1s, multiplier=2, max=60s, jitter=±10%
  • Jitter obligatoire pour éviter les thundering herds synchrones
  • 5 tentatives ≈ 31s d'attente totale (1+2+4+8+16)
  • Implémenter côté client SDK ET côté worker queue serveur

Exemple de code

async function retryWithBackoff<T>(
  fn: () => Promise<T>,
  opts = { maxAttempts: 5, initialMs: 1000, maxMs: 60_000, jitter: 0.1 }
): Promise<T> {
  let lastError: Error | undefined;
  for (let attempt = 0; attempt < opts.maxAttempts; attempt++) {
    try {
      return await fn();
    } catch (err) {
      lastError = err as Error;
      if (attempt === opts.maxAttempts - 1) break;
      const base = Math.min(opts.initialMs * 2 ** attempt, opts.maxMs);
      const jitter = 1 + (Math.random() * 2 - 1) * opts.jitter;
      await new Promise(r => setTimeout(r, base * jitter));
    }
  }
  throw lastError;
}

Voir aussi

Vos préférences cookies

Nous utilisons des cookies pour améliorer votre expérience. Les cookies essentiels sont toujours actifs. Politique cookies.