Les meilleurs cours d'infrastructure ne sont pas dans les livres. Ils tombent à 22 h sur ton infra de production, sans prévenir, et te coûtent une nuit blanche. Ce qui suit est la transcription la plus fidèle possible d'un incident réel sur ORBITECH AI ACADEMY en avril 2026.
Contexte
ORBITECH génère en batch quotidien des milliers d'articles pédagogiques pour la base Alterra. Le pipeline tourne sur un VPS Contabo, fait du scraping de sources publiques (Wikipédia, Education.gouv.fr, sites de programmes officiels), enrichit le contenu via Claude, et stocke en Supabase.
Le VPS Contabo a une seule IPv4 publique, partagée par tous les processus sortants. Pas d'IPv6 active à cette époque. Le pipeline tourne en parallélisme contrôlé : ~12 workers, ~2 requêtes/seconde par worker.
L'incident
22 h 12. Démarrage du run quotidien. Comme d'habitude, le pipeline interroge Google Custom Search pour vérifier la disponibilité de certaines URL et rechercher des sources complémentaires.
22 h 47. Les workers commencent à recevoir des erreurs en cascade :
# Réponse type reçue après 35 minutes de run
HTTP 429 Too Many Requests
Server: gws (Google Web Server)
# Suivi de :
HTTP 403 Forbidden
X-Goog-Error: ip_blocked
Retry-After: 86400 # 24 heures
22 h 51. Diagnostic confirmé : Google a banni l'IPv4 publique du VPS pour 24 heures. Conséquences immédiates :
- Plus aucune requête Google ne passe depuis cette IP
- Le pipeline de génération est cassé pour la nuit et le lendemain
- Les workers continuent de retry et empilent des appels qui meurent
Leçon n° 1 : un service public (Google) peut te bannir unilatéralement
sur n'importe quelle requête sortante. Tu n'as aucun recours immédiat à part attendre
le délai indiqué dans Retry-After.
Pourquoi ?
Mes workers respectaient le quota officiel de Google Custom Search (100 req/jour gratuites,
10 000 req/jour payées). Mais en parallèle, le pipeline faisait aussi des requêtes
HEAD directes vers google.com pour vérifier la disponibilité
de pages — sans clé API. C'est ces requêtes-là, jamais comptabilisées
dans mon esprit, qui ont déclenché le ban.
Du point de vue de Google, ces HEAD non-authentifiés ressemblent à du
scraping. Avec ~24 workers tapant la même IP en parallèle, le seuil heuristique a sauté.
Une seule IP, plusieurs centaines de requêtes par minute, ban.
La correction immédiate (court terme)
Pour reprendre le service avant le déban automatique, j'ai routé toutes les requêtes sortantes du pipeline via Cloudflare WARP (mode SOCKS5 sur le VPS). Cloudflare WARP utilise un pool d'adresses IPv6 — chaque connexion sort donc d'une IP différente.
# /etc/wireguard/wg0.conf — config WARP minimale
[Interface]
PrivateKey = ***
Address = 172.16.0.2/32
Address = 2606:4700:110:8d65::***/128
DNS = 1.1.1.1, 2606:4700:4700::1111
MTU = 1280
[Peer]
PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = engage.cloudflareclient.com:2408
Avec ce setup, le service est revenu en 5 minutes. Mais ce n'est pas une vraie solution : ça déplace simplement le problème vers les pools de Cloudflare, qui peuvent à leur tour être bannis sur certains services.
Le vrai fix (long terme) : fail-fast au démarrage
Le problème de fond, ce n'est pas le ban — c'est que j'ai démarré un pipeline de production avec une configuration réseau insuffisante sans le savoir. La solution, c'est de transformer cette configuration en précondition explicite vérifiée au démarrage. Pas démarrer si la précondition échoue.
// flood-master.js — garde-fou fail-fast
function assertNetworkConfig() {
const ipv6Prefix = process.env.IPV6_PREFIX;
if (!ipv6Prefix) {
console.error("❌ IPV6_PREFIX non défini");
console.error(" Le pipeline refuse de démarrer sans rotation IPv6.");
console.error(" Cause: incident Google ban du 12 avril 2026.");
console.error(" Fix: exporter IPV6_PREFIX=2a05:6e02::/32 puis relancer.");
process.exit(1);
}
// Validation supplémentaire: vérifier que le prefix est routable
if (!/^[0-9a-f:]+\/\d+$/.test(ipv6Prefix)) {
console.error("❌ IPV6_PREFIX format invalide:", ipv6Prefix);
process.exit(1);
}
console.log(`✅ IPv6 prefix actif: ${ipv6Prefix}`);
}
// Appelé AVANT toute initialisation du pipeline
assertNetworkConfig();
Trois éléments important dans ce code :
- L'erreur explique la cause historique — un futur moi (ou un futur collègue) lira ce message à 22 h et comprendra immédiatement
- Le fix est dans le message d'erreur — pas besoin d'aller chercher la doc
- process.exit(1) — pas de mode dégradé, pas de continue-anyway. Le service refuse de démarrer.
Leçon n° 2 : un garde-fou utile refuse de démarrer plutôt que de démarrer dans un état dégradé. Fail-fast > fail-silent à chaque fois qu'on a le choix.
Pourquoi IPv6 résout vraiment le problème
Avec un préfixe IPv6 routé (2a05:6e02::/32 dans mon cas, attribué par mon
FAI), j'ai accès à 2^96 adresses publiques. Le pipeline peut faire
tourner chaque requête sortante sur une IP différente.
Concrètement, ça veut dire qu'aucun service distant ne peut me bannir massivement, parce que mon trafic ressemble à 24 utilisateurs distincts avec 24 IPs différentes. Et ça veut dire qu'un script qui s'emballe et fait 10 000 requêtes en 5 minutes ne brûle pas l'IP de tout mon serveur.
Ce que j'ai changé dans toute mon infra après l'incident
- Garde-fous fail-fast sur les variables d'environnement critiques (IPV6_PREFIX, ANTHROPIC_API_KEY, SUPABASE_SERVICE_KEY) — refus de démarrer en cas d'absence
- Logs structurés sur les codes HTTP 429 et 403, avec push immédiat vers Sentry pour alerting
- Politique de retry exponentiel avec plafond — pas de retry infini sur 429
- Préférence systématique pour les API authentifiées (clé API) plutôt que les requêtes anonymes — le quota authentifié est plus prévisible
- Documentation des incidents dans
memory/feedback_*avec date et cause — pour que la mémoire de l'erreur survive aux refactorings
Conclusion
Le ban Google de 24 heures m'a coûté une nuit. Le garde-fou fail-fast qu'il a engendré me protège pour les 10 prochaines années. Le ratio coût/bénéfice est en ma faveur — à condition de ne pas oublier la leçon.
Le hardening, ce n'est pas configurer le bon firewall avant qu'il ne se passe quelque chose. C'est capitaliser sur chaque incident en transformant la cause en précondition vérifiée. Tant que le code n'oublie pas, je peux oublier — c'est exactement ce que je veux d'une infrastructure.