Reprise sur erreur : dégradation gracieuse à grande échelle
SchemaBridge Team · 2026-01-16 · Resilience, Error Handling, Fault Tolerance
Gérer les retries et les backoffs à grande échelle : comment une résilience managée évite les « Retry Storms ».
Points clés Une logique de retry naïve transforme une panne en retry storm qui fait tomber le service même qu'elle martèle. La résilience repose sur des retries bornés — un backoff exponentiel court pour les échecs HTTP transitoires, un rythme adaptatif lorsqu'un backend signale une surcharge — ainsi que sur des déploiements progressifs avec rollback automatique pour les nouvelles versions de workflow, et sur des outils de reprise humaine (Retry, Resolve, Start over) pour tout ce que l'automatisation ne devrait pas décider.
Le « Retry Storm » : pourquoi la gestion d'erreurs naïve échoue
Aux débuts des systèmes distribués, la « gestion des erreurs » consistait généralement à envelopper un morceau de code dans un try/catch et, éventuellement, à ajouter une simple boucle while pour réessayer trois fois. Cela fonctionne dans un environnement petit et isolé, où les pannes sont rares et localisées. Mais à grande échelle, dans un maillage de microservices interconnectés, les retries naïfs sont la recette d'un effondrement systémique connu sous le nom de Retry Storm (ou « Thundering Herd »).
Imaginez que votre base de données principale devienne légèrement lente sous forte charge pendant les soldes du Black Friday. La latence des requêtes passe de 10 ms à 1100 ms. Votre API applique un timeout standard d'une seconde. Soudain, un millier de workers concurrents atteignent ce timeout simultanément. Tous interceptent l'erreur et, suivant la logique de votre boucle simple, relancent immédiatement la requête.
Votre base de données — qui peinait déjà à traiter les 1 000 requêtes initiales — reçoit alors d'un coup 1 000 requêtes supplémentaires. La charge double instantanément. Le CPU de la base grimpe à 100 % et les latences montent à 5 secondes. Les workers échouent de nouveau, et réessaient de nouveau. Le système entre dans une boucle de rétroaction positive d'échecs. Vous avez de fait lancé un DDoS contre votre propre infrastructure. Vous avez transformé une dégradation mineure des performances en panne totale du système.
Accepter l'échec : les erreurs font partie de l'API
Chez SchemaBridge, nous rompons avec l'idée que les erreurs sont « exceptionnelles ». Dans un monde piloté par les événements, l'échec est aussi courant que le succès. Les réseaux se partitionnent, les pods se comportent de manière erratique et les API tierces ont des fenêtres de maintenance. Nous traitons la reprise sur erreur non pas comme un bloc catch dans votre code, mais comme un cycle de vie managé au sein de la plateforme — avec des limites volontairement strictes sur ce qui est réessayé automatiquement.
Comment SchemaBridge classe les échecs
Pour se rétablir efficacement, il faut d'abord comprendre pourquoi quelque chose a échoué. SchemaBridge prend la décision à deux niveaux :
| Niveau | Échec | Ce qui se passe automatiquement |
| :--- | :--- | :--- |
| Appel HTTP (Gateway) | 5xx, 429 ou erreur d'E/S (timeout, connexion réinitialisée) | Réessayé dans le processus, jusqu'à 3 tentatives supplémentaires avec backoff exponentiel |
| Appel HTTP (Gateway) | Tout autre 4xx (400, 401, 403, 404…) | Non réessayé — un mauvais mot de passe ne réussira jamais à la deuxième tentative |
| Étape (vertex) | Surcharge transitoire d'un backend soumis à une limite de débit (external_overload) | Redispatchée automatiquement, dans la limite d'un budget par vertex |
| Étape (vertex) | Tout le reste | Terminal dès la première tentative ; l'exécution s'affiche en rouge et attend un opérateur |
Le comportement par défaut est volontairement prudent : l'échec d'une étape est permanent sauf preuve qu'il est transitoire. Nous préférons signaler un échec à un humain plutôt que de rejouer silencieusement un effet de bord qu'il n'est peut-être pas sûr de répéter.
Anatomie d'un retry borné : les mathématiques du backoff
Backoff exponentiel pour les appels HTTP
Lorsqu'un appel Gateway rencontre une erreur transitoire, la plateforme ne martèle pas la destination chaque seconde. Elle attend exponentiellement plus longtemps entre les tentatives.
$$Wait = Base \times 2^{Retry - 1}$$
- La tentative initiale échoue
- Retry 1 : attendre 1 s
- Retry 2 : attendre 2 s
- Retry 3 : attendre 4 s
Cela fait quatre tentatives au total, sur environ sept secondes. Si la destination répond 429 Too Many Requests avec un en-tête Retry-After, la plateforme le respecte, dans la limite de 30 secondes. Cette progression courte et bornée absorbe les micro-coupures réseau sans faire d'un service en difficulté une victime. Notez que le backoff n'est pas randomisé — il n'y a pas de jitter — : il est conçu pour lisser une micro-coupure, pas pour coordonner des milliers de clients indépendants.
Redispatch adaptatif pour les backends surchargés
Un backoff court n'est pas le bon outil face à un backend réellement saturé. Pour les types d'étapes soumis à une limite de débit (étapes Gateway et agentiques), un échec pour surcharge est réinjecté dans le contrôle d'admission par destination de la plateforme, qui abaisse le débit auquel il admet du travail vers cette destination (un contrôleur AIMD, la même idée que celle utilisée par TCP pour la congestion). L'étape en échec est ensuite redispatchée automatiquement par ce même chemin d'admission — par défaut jusqu'à 3 fois, configurable par vertex avec maxAutoRetries (réglez-le sur 0 pour une étape dont l'effet de bord ne doit jamais être renvoyé).
{
"type": "GATEWAY",
"config": {
"url": "https://api.example.com/v1/charges",
"method": "POST",
"maxAutoRetries": 5
}
}
Comme le rythme provient du contrôle d'admission et non d'un minuteur fixe, les retries ralentissent exactement autant que la destination l'exige. Si la surcharge dure plus longtemps que le budget, l'étape échoue et l'exécution attend un opérateur.
Rollback progressif : la sécurité des releases de workflows
Parfois, les retries sont vains. Si une nouvelle version de workflow introduit un bug, aucun retry ne le corrigera. Il faut faire un rollback.
SchemaBridge prend en charge les déploiements progressifs avec rollback automatique pour les versions de workflow, implémentés sous forme de workflow système (gradual_deploy).
- Montée en charge : une part configurable du trafic (10 % par défaut, jusqu'à 1 % au minimum) est routée vers la nouvelle version, et cette part est augmentée palier par palier à intervalles.
- Contrôle de santé : à chaque palier, une exécution de monitoring compare le nombre d'erreurs de la nouvelle version à un seuil fixe. En cas de dépassement, le déploiement ramène le trafic de la nouvelle version à 0 %.
Cela limite le rayon d'impact d'une release de workflow défectueuse à la part de trafic qu'elle avait atteinte au moment où le contrôle l'a détectée. Le mécanisme s'applique aux versions de workflow — pas à la configuration d'infrastructure — et c'est un filet de sécurité, pas une garantie : le trafic reçu par la nouvelle version avant le déclenchement du seuil a tout de même été exposé.
Reprise avec intervention humaine : la boîte à outils de l'opérateur
Certains échecs exigent un cerveau, pas une boucle. Si un workflow échoue parce qu'un rapprochement bancaire ne correspond pas au montant de la facture à 0,01 $ près, aucun code ne peut ni ne doit décider de la marche à suivre.
Dans SchemaBridge, une telle exécution se termine simplement en FAILED, avec tout ce dont un opérateur a besoin pour agir :
- Visibilité : l'étape en échec est signalée en rouge sur le graphe de l'exécution et dans le monitor.
- Investigation : un opérateur peut voir l'entrée de l'étape, sa sortie et le message d'erreur (par ex. « mismatch: 100.00 vs 100.01 »).
- L'intervention : l'opérateur choisit la réparation appropriée :
- Retry réexécute l'étape en échec et poursuit le workflow à partir de là.
- Resolve & continue accepte l'échec, enregistre une sortie fournie par l'opérateur pour cette étape et laisse le reste du workflow se poursuivre.
- Start over réexécute l'ensemble du workflow sous forme d'une nouvelle exécution.
- Resume on new version reprend une exécution en échec à partir du point de défaillance sur une version corrigée du workflow.
Les « erreurs » cessent ainsi d'être une source de panique et de bricolages en base de données pour devenir un workflow opérationnel standard.
Scénario illustratif : une panne de passerelle de paiement
Prenons une entreprise SaaS par abonnement qui traite un gros lot de renouvellements chaque nuit à minuit. Une nuit, sa passerelle de paiement principale subit une panne prolongée dans une région.
L'ancienne méthode
Un système hérité reposant sur de simples tâches cron réessaie trois fois lorsque la passerelle tombe, puis marque les abonnements comme « Échec / Paiement refusé ». Le temps que les ingénieurs se réveillent, des comptes clients ont pu être désactivés parce que le système a conclu que leurs paiements avaient été refusés, alors qu'en réalité la passerelle était simplement en panne. La file du support se remplit, et l'attrition suit les e-mails « Compte résilié ».
La méthode SchemaBridge
Imaginez maintenant le même moteur de facturation fonctionnant sur SchemaBridge, en toute honnêteté.
1. Retries bornés : lorsque les 503 commencent, chaque appel de prélèvement est réessayé avec un backoff court. Une micro-coupure est absorbée ; une panne de plusieurs heures ne l'est pas — ces exécutions de renouvellement échouent.
2. Un échec n'est pas une décision : comme une étape en échec arrête son exécution au lieu de suivre une branche « refusé », aucun compte n'est résilié à cause d'une panne interprétée à tort comme un refus. Les exécutions en échec restent dans le monitor, en rouge, avec l'erreur de la passerelle jointe.
3. La reprise est une action groupée : une fois la passerelle rétablie, un opérateur sélectionne les exécutions en échec et les relance en masse.
Le résultat attendu
La panne a tout de même lieu, et quelqu'un doit tout de même agir le matin. Ce qui change, ce sont les dégâts : aucune résiliation erronée, aucun e-mail intempestif, et une reprise qui tient en une seule action groupée au lieu d'un nettoyage de base de données. Voilà la valeur métier de la résilience.
Check-list d'expert pour une conception tolérante aux pannes
Pour construire un système résilient, suivez ces heuristiques :
1. Prévoyez l'annulation de chaque écriture : si vous créez un enregistrement, sachez comment vous le supprimeriez ou l'archiveriez en cas d'échec — même si cette annulation est une étape déclenchée par un humain. La symétrie est la clé de la cohérence.
2. Ajoutez du jitter aux retries des clients que vous maîtrisez : lorsque de nombreux clients indépendants réessaient selon le même calendrier, l'aléa les empêche de se synchroniser en troupeau.
3. Préférez une exécution arrêtée à une mauvaise branche : ne laissez pas une panne d'infrastructure se faire passer pour un résultat métier. Une exécution en échec qui attend un humain vaut mieux qu'une exécution silencieusement erronée.
4. Auditez vos chemins d'erreur : on teste souvent le « Happy Path » en ignorant le « Failure Path ». Dans un environnement de staging, pointez une étape vers un endpoint qui renvoie 503 et 400, et vérifiez que l'exécution se comporte comme vous l'attendez dans chaque cas.
Conclusion : l'échec est une occasion de résilience
La reprise sur erreur ne consiste pas à empêcher les bugs ; elle consiste à empêcher les catastrophes. En bornant les retries automatiques, en laissant la surcharge ralentir le système plutôt que de provoquer une ruée, et en donnant aux opérateurs des outils de reprise précis, vous gagnez la liberté de construire des intégrations complexes sans craindre le « Retry Storm ».
Fait partie de notre série Building the Bridge. Voir aussi : L'infrastructure en tant que workflow sur la gestion des ressources cloud avec une logique visuelle.