Résumé
Le 19 janvier 2026, entre 14 h 02 et 14 h 28 UTC, environ deux tiers de toutes les tentatives de connexion au panneau ou d'authentification contre l'API ont échoué. Les sessions existantes ont également été invalidées de manière aléatoire. Les instances en cours d'exécution, leur réseau et leur trafic n'ont pas été affectés tout au long de l'incident. Le provisionnement a été mis en pause pendant vingt-six minutes puis a été traité; aucune commande n'a été perdue.
Chronologie
Toutes les heures sont en UTC, le 19 janvier 2026.
| Heure | Événement |
|---|---|
| 14:02 | Modification du schéma des jetons de session appliquée au plan de contrôle. Le déploiement a été marqué comme configuration, donc il est allé sur les six nœuds du panneau en même temps. |
| 14:03 | Le taux d'erreur de connexion passe de près de zéro à soixante et un pour cent. L'alerte automatisée a une fenêtre de deux minutes et ne se déclenche pas encore. |
| 14:06 | L'alerte se déclenche. Ingénieur d'astreinte contacté. |
| 14:08 | Premier intervenant en ligne. Il voit un taux d'erreur, aucun déploiement dans le journal des modifications de code, et commence à examiner la base de données. |
| 14:14 | Un deuxième ingénieur rejoint, vérifie le journal des modifications de configuration plutôt que celui du code, et trouve l'entrée de 14:02. |
| 14:16 | Cause comprise : deux nœuds valident les jetons avec l'ancien lecteur. |
| 14:19 | Début du rollback. |
| 14:24 | Les jetons sont émis et validés correctement sur les six nœuds. Le taux d'erreur retombe à zéro. |
| 14:28 | Les travaux de provisionnement en file d'attente sont traités. Récupération terminée. |
| 15:10 | Page de statut mise à jour. Quarante-deux minutes de retard, ce qui constitue un échec en soi et est traité ci-dessous. |
Cause racine
Le jeton de session a gagné un champ. Les émetteurs ont immédiatement produit le nouveau format; le lecteur sur deux des six nœuds du panneau n'avait pas été redémarré et rejetait tout élément portant le nouveau champ. Les requêtes sont réparties sur les six nœuds, donc une session créée sur un nouveau nœud avait environ une chance sur trois d'être validée par un ancien nœud lors d'une requête donnée. Le résultat semblait intermittent, c'est pourquoi les six premières minutes de diagnostic ont été consacrées à la base de données plutôt qu'au journal de déploiement.
La cause plus profonde est une règle que nous avons écrite en 2023. Les modifications qui touchent un fichier de schéma plutôt que le code applicatif étaient classées comme configuration, et la configuration ignorait l'étape de canari au motif que ce n'était, entre guillemets, que des valeurs. Cette règle était raisonnable quand les seuls fichiers de schéma étaient des feature flags. Personne ne l'a revue à mesure que la définition d'un fichier de schéma s'est élargie, et cette modification a été correctement classée sous une règle qui était devenue silencieusement erronée.
Ce n'est pas une erreur de l'ingénieur qui l'a appliquée. La classification a été suivie exactement comme écrit.
Rayon d'impact
- Connexions au panneau : taux d'échec de soixante et un pour cent pendant vingt-six minutes.
- Jetons API : même taux d'échec, même fenêtre. Les clés d'idempotence ont fait que les créations retentées n'ont pas été dupliquées.
- Instances en cours d'exécution : non affectées. Aucune perte de paquets, aucun redémarrage, aucun impact sur le stockage.
- Provisionnement : en pause, pas en échec. Quatre commandes ont été réglées pendant la fenêtre et toutes les quatre ont été complétées à 14:28.
Ce que nous avons changé
- L'étape de canari est désormais inconditionnelle. Tout ce qui est déployé, quelle que soit la classification, va sur un nœud pendant cinq minutes avec du trafic synthétique avant d'aller ailleurs. Fait le 21 janvier.
- Les lecteurs acceptent le format précédent pendant trente jours. La validation des jetons est désormais explicitement versionnée avec une fenêtre de chevauchement, de sorte qu'un changement partiellement déployé ne dégrade en rien. Fait le 23 janvier.
- Une connexion synthétique s'exécute toutes les quinze secondes depuis l'extérieur de notre réseau, dans trois régions, et déclenche une alerte dès la deuxième défaillance consécutive plutôt qu'après une fenêtre de moyenne de deux minutes. Fait le 22 janvier.
- La page de statut est publiée automatiquement lorsque la connexion synthétique échoue deux fois, sans attendre qu'un humain rédige une phrase. Une phrase humaine suit. Fait le 26 janvier.
Ce que nous n'avons pas changé, et pourquoi
Nous ne journalisons toujours pas les adresses IP clientes ni les corps de requête pour le trafic du panneau. Les avoir aurait montré immédiatement la distribution de un sur trois entre les nœuds et aurait probablement gagné neuf minutes. Neuf minutes ne valent pas un enregistrement permanent de l'endroit d'où chaque client se connecte. Le tableau de rétention sur la page de journalisation reste inchangé.
Nous n'avons pas déplacé les sessions dans un magasin partagé intersites. Un magasin de sessions unique couvrant tous les sites aurait évité complètement le problème du lecteur mixte en ayant un seul lecteur. Cela créerait également exactement l'enregistrement centralisé, toujours chaud, de qui est connecté à quoi, que nous avons passé six ans à ne pas construire.
Nous n'avons pas ajouté de canal d'annonce de panne en dehors de la page de statut. Plusieurs personnes ont suggéré les réseaux sociaux. La page de statut est la seule chose que nous exploitons dont nous pouvons nous engager à maintenir l'exactitude, et ajouter une deuxième surface signifie une deuxième surface qui devient obsolète.
Le crédit
Le SLA couvre la disponibilité des instances. Les instances ont été disponibles pendant les vingt-six minutes, donc selon le contrat, personne ne devait rien. Nous avons appliqué un crédit d'un jour à chaque compte ayant eu une authentification échouée pendant la fenêtre, ce qui s'est élevé à environ trois mille cent euros, car argumenter la distinction avec des personnes qui ne pouvaient pas atteindre leurs serveurs est une moins bonne utilisation de l'après-midi de tout le monde.