Dev ISO prod : la règle que nous nous sommes imposée après un incident évitable
Post-mortem : un webhook jamais exécuté en développement, une colonne de base manquante en dev — deux incidents, une règle : aucun chemin de code ne s'exécute pour la première fois en production.
Les post-mortems publics sont un genre à risque : on y étale ses erreurs. On y gagne mieux : la mémoire institutionnelle et, on l'espère, quelques lecteurs qui éviteront la même. Voici comment deux incidents sans gravité — parce qu'attrapés à temps — ont accouché d'une règle désormais non négociable chez nous : le développement doit être iso-production. Aucun chemin de code ne doit s'exécuter pour la première fois devant de vrais clients.
Incident n° 1 : le webhook qui n'avait jamais tourné
Le décor : notre facturation repose sur les webhooks Stripe — un paiement
aboutit, Stripe nous notifie, les droits du client s'activent. En
production, ce chemin exige un point d'entrée public. En développement,
il exige un outil de tunnel (stripe listen) qui relaie les événements
vers la machine locale… et que personne ne lançait, parce que rien ne
l'exigeait : les paiements de test « marchaient », l'interface affichait
le succès, et les droits se mettaient à jour par d'autres chemins pendant
les tests manuels.
Résultat : pendant des semaines, le chemin le plus critique de la chaîne de facturation — la réception du webhook, sa vérification de signature, la mise à jour des droits — n'avait jamais été exécuté dans un environnement vivant. Il était couvert par des tests unitaires, oui. Mais entre « la fonction est testée » et « le flux complet a tourné avec de vrais messages signés », il y a exactement l'espace où vivent les mauvaises surprises : une signature vérifiée contre le mauvais secret, un port qui n'écoute pas, un événement au format inattendu.
La correction technique a pris une heure. La vraie correction est organisationnelle : le script de développement lance désormais l'écoute des webhooks d'office — le chemin critique tourne des dizaines de fois par jour, par tout le monde, sans y penser.
Incident n° 2 : la migration fantôme
Quelques mois plus tard, variante du même thème. Une évolution ajoute une colonne en base de données. La suite de tests passe — elle migre sa propre base isolée à chaque exécution. Le serveur de développement, lui, lit la base de dev réelle… qui n'avait pas reçu la migration. Résultat : des écrans cassés en local sur des fonctions sans rapport avec le changement, et vingt minutes à chercher un bug qui n'existait pas dans le code — il existait dans l'écart entre deux environnements.
Même famille : les tests vivaient dans un monde (base migrée automatiquement), le développement dans un autre (base migrée quand on y pense), la production dans un troisième (base migrée au déploiement). Trois mondes, trois comportements possibles pour le même commit.
La règle, et ce qu'elle implique concrètement
D'où la règle, écrite noir sur blanc dans nos conventions internes : toute dépendance de la production tourne aussi en développement, configurée de la même façon. En pratique :
- Si la production a un Redis, le développement a un Redis — pas un repli « en mémoire, c'est pareil ». Les replis dégradés restent des filets de sécurité d'exécution, jamais un mode de développement.
- Les services annexes (webhooks, files, emails) démarrent avec l'environnement, pas sur demande. Ce qui exige une action volontaire finit par ne plus être fait.
- Les migrations s'appliquent à la base de dev réelle avant tout redémarrage de serveur — et l'oubli se détecte au démarrage plutôt qu'au premier écran cassé.
- Les preuves se rejouent « à froid » : vider les caches de build avant d'annoncer qu'une correction fonctionne, parce qu'un cache chaud sait masquer une erreur toute neuve.
Le coût de cette règle est réel et il faut le dire : l'environnement de développement est plus lourd (plusieurs services par produit, orchestrés par un fichier compose), le poste de travail doit suivre, et l'installation d'un nouveau venu prend une heure de plus. Nous considérons ce coût comme une prime d'assurance — payée en confort, remboursée en incidents qui n'ont pas lieu.
La leçon générale
Ces deux incidents ont un point commun instructif : aucun des deux n'était un bug de code. Le code était correct les deux fois. C'est l'écart entre environnements qui créait le risque — un risque invisible aux tests unitaires, invisible à la revue de code, visible seulement en faisant réellement tourner le système complet. D'où notre conviction, au-delà de cette règle : la qualité ne se joue pas seulement dans le code, elle se joue dans la fidélité de l'environnement où on l'éprouve. Si votre équipe dit « ça marchera en prod, c'est juste le dev qui est différent » — c'est précisément la phrase qui précède les incidents évitables.
Deux articles voisins.
Vous avez le même problème ?
C'est souvent comme ça que les missions commencent. Décrivez votre contexte, on vous dit ce qu'on en pense sous 24 h.
Décrire votre projet