Résumé

  • La panne réseau du 9 octobre et celle du pool de base de données le 10 étaient distinctes, mais toutes deux ont interrompu l’exécution à travers des dépendances partagées.
  • Certaines exécutions ayant subi un échec interne sont restées Running. Les gestionnaires d’échec n’ont pas été appelés et les clients ont dû annuler ou rejouer les traitements.

Une exécution durable porte une promesse simple : un travail peut attendre, reprendre après une interruption et conserver les étapes terminées. Le récit qu’Inngest fait des 9–11 octobre révèle les conditions cachées de cette promesse. Où l’état d’une exécution est-il stocké ? Quelles files partagent un même chemin de traitement ? Quel statut est inscrit lorsqu’une dépendance interne échoue ? Qui apprend qu’un traitement ne repartira pas de lui-même ?

Inngest décrit deux incidents, pas une seule panne prolongée. Le 9 octobre à 21 h 05 UTC, un fournisseur a perdu la connectivité entre un de ses centres de données et les autres centres d’Inngest, ainsi que l’accès sortant à Internet. Selon l’entreprise, l’explication préliminaire du fournisseur était une erreur lors d’une modification de la configuration anti-DDoS ; le rapport complet était encore attendu. La connectivité est revenue à 21 h 49. Le 10 octobre, les deux pools PgBouncer devant la base principale ont perdu toutes leurs connexions à 14 h, puis de nouveau à 15 h 30.

La planification des exécutions et le traitement des files ont été bloqués pour la plupart des comptes. Une mesure de mitigation a rétabli le traitement, puis provoqué des délais intermittents, surtout pour les fonctions cron, jusqu’au retour au pool d’origine le 11 octobre à 4 h 17 UTC. Le routage des passerelles a été amélioré le lendemain. Les mécanismes et les chemins de reprise étaient différents.

Le 9 octobre, l’architecture a amplifié une panne localisée. Inngest indique fonctionner dans trois centres de données : un compte pouvait être traité dans un centre alors que l’état requis se trouvait dans un autre ; la base centrale et les pools de connexions dépendaient encore d’un autre fournisseur. Quand le chemin inter-centres a échoué, certains travailleurs ne pouvaient ni consulter les paramètres du compte ni sauvegarder l’état de l’exécution. L’impact ne s’est pas arrêté là. Les travaux en échec ont grossi une file d’événements partagée, retardant des comptes sans dépendance directe envers le centre isolé.

Les comptes disposant d’une file dédiée n’ont pas été touchés. Une dépendance peut donc s’étendre au-delà des comptes qui l’utilisent directement lorsque la file de traitement est mutualisée.

Le lendemain, le couplage était ailleurs. Selon Inngest, des délais courts sur les recherches de base ont interagi avec l’annulation des requêtes et PgBouncer. Certaines requêtes attendaient encore une connexion lorsque leur délai expirait. Le pilote a fermé la connexion cliente ; plus tard, PgBouncer a exécuté la requête abandonnée, puis fermé la connexion à la base au lieu de la rendre au pool. Comme les nouvelles connexions étaient ouvertes une par une, les pertes ont dépassé les remplacements.

Ces effondrements ont coïncidé avec les pics cron du début et de la fin de l’heure, qui triplaient environ le volume de requêtes, et avec le déploiement récent de nouvelles recherches qui échouaient en grand nombre. Redémarrer les pools n’était pas fiable ; augmenter leur taille ne résolvait pas le débit limité d’ouverture des connexions.

La parade a introduit un autre chemin. Le déplacement vers les pools gérés à côté de la base a rétabli le traitement entre 16 h 10 et 16 h 25 UTC. Mais ce routage traversait des passerelles de traduction d’adresses réseau qui abandonnaient silencieusement certaines connexions. Une requête pouvait alors attendre jusqu’à 16 minutes avant d’échouer, avec des retards particulièrement visibles sur les fonctions cron. Inngest a replacé la planification cron sur les pools initiaux le 11 octobre à 4 h 17 UTC et amélioré le routage le 12.

Une mitigation modifie la topologie : elle peut retirer un goulot d’étranglement tout en créant un nouveau délai difficile à observer.

La transition d’état a posé une question plus importante. Inngest explique que les erreurs internes comptaient dans les tentatives configurées. Lorsqu’une étape échouait définitivement à cause d’une erreur interne, certaines exécutions restaient Running au lieu de passer à Failed. Le gestionnaire onFailure n’était alors pas déclenché et un parent en attente via step.invoke ne recevait pas d’échec. Inngest dit que ces exécutions ne reprenaient pas seules ; les clients devaient les annuler ou les rejouer. Le rétablissement d’un pool de travailleurs ne garantissait donc pas que chaque processus métier interrompu ait atteint un état terminal.

Ce cas diffère d’une reprise ordinaire. La documentation d’Inngest explique que les résultats d’étapes achevées peuvent être réutilisés lors d’une reprise, tandis que les étapes sont retentées séparément. Mais le rapport indique qu’un rejeu client repart du début. Les étapes terminées peuvent donc être exécutées une nouvelle fois. Cela ne prouve pas qu’un paiement, un message ou une écriture a été doublé. Cela oblige cependant l’opérateur à examiner la trace et à vérifier que la répétition est sans danger.

Les recommandations d’idempotence d’Inngest rappellent qu’un service externe peut accepter une action avant que le moteur enregistre son résultat ; la tentative suivante peut alors répéter l’appel. Un point de contrôle durable conserve la progression dans l’orchestrateur, mais ne rend pas chaque effet externe « exactement une fois ».

Inngest affirme avoir livré plusieurs corrections : les recherches n’annulent plus les requêtes en attente d’une connexion ; une erreur interne définitive marque désormais l’exécution comme échouée ; si l’état est momentanément illisible, le travail reste en file et reprend lorsque l’état redevient accessible. Le routage et la mise à jour de la page de statut ont également été améliorés. La réponse architecturale plus vaste — consolidation dans un seul centre de données — était encore en cours. Le rapport ne décrit ni la topologie finale ni son dispositif indépendant de reprise après sinistre.

Sources