Vous avez un troisième type de dette technique. Personne n'a créé d'outil pour la détecter.

10 min read

Vous lancez votre app habituelle. ERREUR. Vous êtes déjà énervé parce que vous n'aviez pas prévu de faire de la maintenance aujourd'hui. Alors vous creusez. Mon terminal m'a balancé ECONNREFUSED 127.0.0.1:46279 en pleine figure et il m'a fallu exactement trente secondes pour comprendre que personne, nulle part, n'allait s'occuper de ça. Pas de page de statut. Pas de ticket à créer. Pas de SLA à agiter. Le service gratuit dont dépendait une partie de ma pipeline venait de tomber, et le seul humain sur Terre que ça préoccupait, c'était moi.

Bien sûr, je n'avais jamais signé de contrat avec eux. J'utilisais un service gratuit. Je n'apparaissais sur aucun de leurs tableaux de bord. Et pourtant, à 9h17 ce lundi matin, ils me devaient quelque chose qu'ils ne savaient même pas qu'ils me devaient. Ou plutôt l'inverse : c'est moi qui leur devais. J'avais accumulé une ardoise pendant des mois sans m'en rendre compte, et le créancier venait de la présenter.

TLDR (Vous connaissez la dette technique que vous avez écrite. Vous mesurez la dette technique héritée de vos dépendances. Il y a une troisième pile dont personne ne parle : la dette que vous importez chaque fois que vous branchez un SaaS gratuit dans votre pipeline. Elle n'apparaît sur aucun tableau de bord. Aucun linter ne la détecte. Dependabot ne la voit pas. Auditez votre dette importée avant qu'un lundi matin ne s'en charge pour vous.)

BD style années 90 : développeur à un bureau encombré avec messages d'erreur, collègue pointant un diagramme au tableau sur les coûts cachés, homard sur avion en papier en arrière-plan
Les outils gratuits ne sont pas gratuits. Votre dette technique vient de gagner un troisième colocataire.

Les Trois Piles

Il y a trois types de dette technique et la plupart des équipes n'en comptent que deux.

La première, c'est la dette que vous avez écrite. Le hack du vendredi après-midi qui a survécu. Le TODO de 2022 devenu critique. Le if qui était censé être temporaire et qui a maintenant son propre historique de commits. Vous savez qu'elle existe parce que vous l'avez écrite, et vous savez à peu près où elle se trouve parce que la mauvaise odeur vous suit partout. Votre linter en attrape une partie. La code review en attrape une autre. Le reste vit dans votre tête.

La deuxième pile, c'est la dette que vous avez héritée. Des lockfiles pleins de dépendances transitives que vous n'avez jamais choisies. Des librairies qui n'ont pas livré depuis trois ans mais qui s'installent encore. Des packages avec deux mainteneurs dont l'un vient de partir élever des chèvres. Vous savez que cette pile existe aussi, parce qu'il y a des outils pour ça. npm audit, Dependabot, Snyk, Renovate. Ils vous gueulent dessus tous les lundis matin que vous le vouliez ou non. Ces cris sont agaçants, mais au moins quelqu'un crie.

Puis il y a la troisième pile. La pile pour laquelle vous n'avez pas de nom, parce que personne ne l'a nommée. Le service gratuit que vous branchez dans une étape de votre pipeline parce que c'était plus simple que de construire le truc vous-même. L'API hébergée qui traite une partie de vos données parce qu'ils avaient un tier gratuit généreux. Le endpoint webhook qui fait une conversion que vous n'alliez jamais écrire vous-même. Aucune de cette dette n'est dans votre codebase. Rien n'apparaît dans package.json. Aucun outil ne la surveille. Vous ne la comptez même pas comme une dépendance dans votre tête, parce que les dépendances sont des choses qu'on importe et ces trucs sont des choses qu'on appelle.

Mais ce sont des dépendances. Et c'est de la dette. La dette est juste assise ailleurs, sur le serveur de quelqu'un d'autre, avec les incitations de quelqu'un d'autre. Vous ne l'avez pas émise. Vous l'avez importée.

La dette que vous n'avez pas émise reste votre dette dès qu'elle tombe.

Pourquoi Personne Ne La Voit

La raison pour laquelle personne ne voit cette troisième pile est structurelle, pas stupide.

Tous les outils qu'on a construits pour mesurer la dette technique regardent à l'intérieur de votre codebase. Les linters analysent vos fichiers. Dependabot lit vos manifestes. Snyk scanne votre lockfile. La code review se fait sur vos PRs. Toute la stack d'observabilité assume que la dette vit dans des artefacts que vous possédez et que vous pouvez grepper. La dette importée ne vit pas dans des artefacts que vous possédez. Elle vit à une URL. Et une URL n'est pas un asset, c'est une promesse.

Une promesse faite par une entité qui ne vous doit rien.

Il y a aussi une raison plus subtile. Vous n'avez pas importé ces trucs exprès. Vous les avez importés un mardi après-midi quand vous aviez besoin d'une conversion rapide, vous avez googlé, trouvé un endpoint gratuit, collé l'URL dans un fichier de config, et vous êtes passé à autre chose. Ça ressemblait à utiliser un outil, pas à signer un contrat. Rien dans votre éditeur ne vous a dit que vous veniez de boulonner la mortalité d'un inconnu à votre pipeline. Donc vous n'avez mis à jour aucun registre mental. Il n'y avait pas de registre.

Le truc marrant, c'est que le reste de l'industrie sait parfaitement que ces trucs cassent. Une enquête 2025 auprès de 1 000 dirigeants tech seniors a trouvé que 93% s'inquiètent de l'impact des pannes et 100% ont subi des pertes de revenus liées aux pannes cette année-là. La liste des incidents publics ressemble à un catalogue d'horreur : AWS us-east-1 qui tombe pendant des heures et entraîne les fournisseurs SaaS dépendants, les règles WAF de Cloudflare qui effacent un morceau du trafic global en un seul push, les erreurs de configuration Azure qui plantent Microsoft 365 et Xbox en même temps. On sait que les pannes arrivent. On les traque publiquement. On écrit des postmortems.

Mais on les traque après. Il n'existe pas d'outil qui entre dans votre repo et dit "vous dépendez d'une poignée de trucs qui pourraient disparaître demain et vous avez un plan pour zéro d'entre eux." Cet outil n'existe pas parce que les inputs ne sont pas dans votre repo. Ils sont éparpillés dans des appels HTTP dans des fichiers random, des URLs hardcodées dans la config, des fetch statements enterrés dans des modules de service, des variables d'env qui pointent vers des hostnames que vous avez notés une fois et oubliés.

Vous savez à quoi ressemble votre package.json. Vous n'avez aucune idée de ce à quoi ressemblent vos appels sortants. C'est ça, le gap.

L'Audit Que Personne Ne Lance

Après que le backend Excalidraw de Kroki ait planté et refusé de revenir, je me suis assis pour la première fois en années et j'ai lancé l'audit. Pas celui pour les packages npm. Celui pour les appels HTTP sortants vers des services gratuits que je n'avais jamais payés et que je ne pouvais pas remplacer rapidement.

Il m'a fallu un samedi matin pour tout grepper. La pipeline sur laquelle je travaillais à l'époque était une automatisation de catalogue produit pour un petit client ecommerce, le genre de truc qui génère des diagrammes d'assemblage et des specs visuelles pour les pages produit de leur boutique. Pas glamour, mais ça livre tous les jours. Et chaque étape de la pipeline avait un SaaS gratuit branché dessus quelque part.

J'ai trouvé 14 appels sortants vers des services que je n'avais jamais payés. Je ne vais pas vous ennuyer avec l'inventaire complet. Les chiffres intéressants étaient ailleurs. Le nombre d'items qui avaient un plan de fallback documenté quelque part : zéro. Le nombre d'items avec du monitoring sur le service upstream : zéro. Le nombre d'items que j'avais déjà stress-testés en tuant la dépendance exprès : zéro aussi.

Je faisais tourner une pipeline de prod sur une pile de promesses gratuites, et je le faisais depuis si longtemps que ça ne s'enregistrait même plus comme un risque. Ça s'enregistrait comme de "l'infrastructure."

Le remplacement de Kroki, le vrai fix, était petit. Un seul fichier TypeScript qui fait exactement ce que le service cassé faisait pour moi, ni plus, ni moins. Tourne sur Bun. Appelle une librairie directement au lieu de passer par un navigateur headless. Vit en 47 lignes. Utilise 93MB de RAM. Rend un diagramme en environ 2 millisecondes. Il tourne dans un container Docker sur un VPS que je payais déjà 6€ par mois, sur le même réseau interne que le reste de la stack. Pas d'endpoint public. Pas de certificats. Pas de surface d'attaque. Il tourne depuis le jour où je l'ai écrit et il n'est jamais tombé une seule fois.

Maintenant, la partie qui me dérange est récente. Il y a cinq ans, ce fix m'aurait pris une journée entière. Peut-être deux. Le coût-bénéfice de remplacer une dépendance gratuite aurait été une perte nette pour n'importe laquelle d'entre elles, donc j'aurais fait ce que tout le monde fait, c'est-à-dire attendre que l'upstream revienne et prier. Aujourd'hui, avec Claude Code devant moi, le même fix m'a pris trente minutes et je l'ai fait pendant une pause café. Les maths ont basculé. Le truc qui était trop cher à réparer est maintenant trop bon marché à ignorer.

Comme quand j'ai reconstruit un setup payant que le vendeur a décidé de retirer, pour une fraction du coût il y a quelques mois. L'arbitrage a changé sous nos pieds, et la plupart d'entre nous font encore tourner les anciens prix dans leur tête.

Chaque dette importée que je portais depuis des années était soudain bon marché à refinancer. Je ne l'avais juste pas remarqué.

Le Fix N'Est Pas L'Auto-Hébergement

Attention ici, parce que la version facile de cette histoire c'est "auto-hébergez tout" et c'est la mauvaise conclusion.

L'auto-hébergement a sa propre dette. Les serveurs ont besoin de patches. Les containers ont besoin de redémarrages. Les disques se remplissent. Le fait que j'aie remplacé une dépendance gratuite par 47 lignes de mon propre code ne veut pas dire que j'ai gagné la partie. Ça veut dire que j'ai échangé un créancier contre un autre. Le nouveau créancier, c'est moi, et au moins je sais où me trouver.

Le vrai fix est beaucoup plus ennuyeux. Le vrai fix c'est tenir un bilan.

Vous n'avez pas besoin d'un outil. Vous avez besoin d'une liste. Un fichier texte plat dans votre repo, ou une section dans votre README, ou ce qui survit à votre propre flemme. Chaque service externe que votre pipeline appelle. Trois colonnes. Ce qu'il fait, ce qui meurt s'il meurt, et ce que vous feriez à ce sujet un lundi matin. C'est tout. L'acte de l'écrire vous force à regarder chaque ligne et à poser la seule question qui compte : est-ce que j'ai un plan, ou est-ce que je parie que celui-ci est trop gros pour tomber ?

La plupart des vôtres n'auront pas de plan. C'est bien. Le but de l'audit n'est pas de tout réparer en un weekend, c'est de rendre la troisième pile visible. Une fois que vous pouvez la voir, vous pouvez commencer à refinancer les items les moins chers en premier. Les remplacements de deux millisecondes. Les fixes de 47 lignes. Ceux où la librairie existe en package et la seule chose pour laquelle vous payiez était le wrapper HTTP.

Vous découvrirez, comme moi, qu'un nombre surprenant de vos dettes importées sont exactement ça : un wrapper HTTP autour de quelque chose que vous auriez pu appeler directement. L'infrastructure avait l'air impressionnante parce qu'il y avait un dashboard hébergé et une page de statut et une marque. Enlevez le wrapper et la vraie logique fait cinquante lignes. C'est le même pattern que je retrouve ailleurs aussi, et c'est pourquoi j'ai écrit tout un article sur comment l'outil le moins cher qui fait le boulot tend à battre le fancy en production. Moins de surface, moins à casser, moins de dépendances.

Trois questions à mettre au bilan, pour chaque ligne.

Première question : si ce truc meurt un lundi matin à 9h, qu'est-ce qui arrête de marcher ? Soyez honnête. Ne dites pas "rien de critique." Déroulez. Tracez l'appel. Voyez où ça atterrit. Si la réponse est "l'étape de publish" ou "le truc côté client" ou "la partie qui fait du fric," entourez la ligne en rouge.

Deuxième question : est-ce que j'ai un fallback, ou est-ce que je crois juste que celui-ci est trop gros pour tomber ? Le raisonnement "trop gros pour tomber" est exactement le raisonnement qui vous tue. Cloudflare est trop gros pour tomber. AWS us-east-1 est trop gros pour tomber. Ils sont tous les deux tombés en 2025. Les tiers gratuits de mainteneurs indés tombent toutes les semaines. La croyance n'est pas un fallback.

Troisième question, c'est la bon marché. Combien de lignes de code ça me coûterait de reconstruire ça moi-même, maintenant, pendant que je suis calme, au lieu de dans la panique à 9h17 un lundi ? Peut-être que la réponse est "des milliers" et vous décidez de vivre avec le risque. C'est une vraie décision. Peut-être que la réponse est "47" et vous le faites pendant une pause café. C'est une vraie décision aussi. Le but c'est de prendre la décision au lieu de la subir.

La plupart d'entre nous n'ont jamais pris la décision. On a juste continué à cliquer le service gratuit dans la pipeline parce qu'il était là.


Trois jours après l'incident, je suis retourné sur la page de statut de Kroki. Le backend Excalidraw était toujours listé comme down. Quelqu'un avait posté un message sur leur Discord pour demander si quelqu'un travaillait dessus. Personne n'avait répondu.

Ma pipeline tournait depuis 72 heures sans interruption. J'avais oublié que je devais quelque chose à quelqu'un.

L'IA vous rend résilient ou égoïste. Ça dépend comment vous louchez. 🤷

Bref, le point c'est ça : auditez votre dette importée. Pas parce que vous devez tout réparer, mais parce que vous devez la voir. La dette que vous pouvez voir, vous pouvez la planifier. La dette que vous ne pouvez pas voir attend juste un lundi matin.

Sources

(*) L'image de couverture a été faite par une IA, qui est elle-même un service gratuit que j'importe dans mon workflow. Tirez-en les conclusions que vous voulez.