Les gestionnaires de paquets qui utilisent Git comme base de données finissent par échouer
(nesbitt.io)- Plusieurs gestionnaires de paquets ont utilisé Git comme une base de données pour profiter de la gestion de versions et de la collaboration, mais à mesure que l’échelle augmente, ils se heurtent à des problèmes de performances et de maintenance
- Cargo, Homebrew et CocoaPods, entre autres, ont finalement migré vers des index basés sur HTTP ou des CDN en raison de la croissance de la taille des index Git, de la lenteur des mises à jour et de l’inefficacité dans les environnements CI
- vcpkg continue de fonctionner sur la base de hachages d’arbres Git, ce qui provoque des échecs de build et des contournements complexes dans les environnements en shallow clone
- Le système de modules Go a introduit GOPROXY et une base de données de sommes de contrôle (sumdb) afin d’éliminer la dépendance à Git et d’améliorer la sécurité comme la vitesse
- Git est excellent pour la collaboration sur le code, mais il apparaît de façon répétée qu’il est mal adapté aux requêtes sur les métadonnées de paquets et à la gestion de registres à grande échelle
Les échecs répétés des tentatives d’utiliser Git comme base de données
- Git est attractif grâce à ses avantages comme l’historique des versions, l’architecture distribuée et l’hébergement gratuit, mais son utilisation comme base de données se heurte à des limites de montée en charge
- Plusieurs gestionnaires de paquets ont adopté Git comme index, mais avec le temps les dégradations de performances et la charge d’infrastructure se sont aggravées
Cargo
- L’index de crates.io a commencé comme un dépôt Git, et tous les clients effectuaient un clone complet
- À mesure que le dépôt grossissait, un goulot d’étranglement de performance dans libgit2 est apparu pendant l’étape de delta resolution
- Dans les environnements CI, l’index complet était téléchargé à chaque build, entraînant un gaspillage important
- Via la RFC 2789, le protocole sparse HTTP a été introduit afin de ne récupérer via HTTPS que les métadonnées nécessaires
- En avril 2025, 99 % des requêtes utilisent le mode sparse
- L’index Git existe toujours, mais la majorité des utilisateurs n’y accèdent plus
Homebrew
- GitHub a demandé à Homebrew de cesser d’utiliser les shallow clones, en signalant que les mises à jour étaient des « opérations très coûteuses »
- Le dossier
.gitde homebrew-core approche 1 Go, et les mises à jour subissent des lenteurs liées à la delta resolution
- Le dossier
- En février 2023, avec Homebrew 4.0.0, la mise à jour des taps a basculé vers un téléchargement au format JSON
- La suppression de
git fetcha accéléré les mises à jour, et la fréquence des mises à jour automatiques est passée de 5 minutes à 24 heures
- La suppression de
CocoaPods
- Le gestionnaire de paquets CocoaPods pour iOS/macOS a vu son dépôt Specs, composé de plusieurs centaines de milliers de podspecs, devenir excessivement volumineux
- Le clonage et les mises à jour prenaient plusieurs minutes, et l’essentiel du temps CI était consommé par les opérations Git
- GitHub a appliqué une CPU rate limit, en désignant les shallow clones comme cause de la charge serveur
- L’équipe a mis en place des mesures temporaires comme l’arrêt des fetch automatiques, le passage au clone complet et le sharding du dépôt
- À partir de la version 1.8, le projet est passé à une distribution HTTP basée sur CDN, économisant environ 1 Go d’espace disque côté utilisateur et améliorant fortement la vitesse d’installation
Nixpkgs
- Nix évite déjà le clonage Git côté client en utilisant des channels basés sur des tarballs
- Les expressions de paquets sont fournies en HTTP depuis S3 et un CDN
- Cependant, l’infrastructure de GitHub est sous pression à cause d’un dépôt de 83 Go et de 20 000 forks
- En novembre 2025, GitHub a signalé des échecs de consensus entre réplicas et des erreurs lors des opérations de maintenance
- Le clone local fait 2,5 Go, mais l’ensemble du réseau de forks exerce une pression sur l’espace de stockage de GitHub
vcpkg
- Le gestionnaire de paquets C++ de Microsoft, vcpkg, utilise des hachages d’arbres Git pour le versionnement
- Avec
builtin-baseline, il faut l’historique complet pour reproduire les ports à un commit donné
- Avec
- Dans les environnements en shallow clone (GitHub Actions, DevContainers), cela provoque des échecs de build
- La solution consiste à définir
fetch-depth: 0, ce qui impose le téléchargement de l’historique complet
- La solution consiste à définir
- En raison de la structure des hachages d’arbres Git, le suivi des commits est impossible, et cette limite structurelle ne peut pas être corrigée
- Le projet ne prend toujours en charge que des registres basés sur des dépôts Git, sans alternative HTTP ni CDN
Système de modules Go
- L’équipe d’ingénierie de Grab a réduit le temps de
go getde 18 minutes à 12 secondes après l’introduction d’un proxy de modules - L’ancienne méthode obligeait à cloner le dépôt complet de chaque dépendance pour pouvoir lire
go.mod - L’équipe Go s’inquiétait de la dépendance aux outils VCS et des vulnérabilités de sécurité
- Depuis Go 1.13, GOPROXY est la valeur par défaut, et les sources des modules ainsi que
go.modsont fournis en HTTP- sumdb (base de données de sommes de contrôle) garantit l’intégrité et la pérennité des modules
Problèmes généraux quand Git est utilisé comme base de données
- Le wiki basé sur Git (Gollum) devient lent pour la navigation dans les répertoires et le chargement des pages sur de gros dépôts
- GitLab prévoit d’abandonner Gollum
- Le CMS basé sur Git (Decap) atteint la limite de 5 000 requêtes de l’API GitHub
- Les performances se dégradent au-delà d’environ 10 000 entrées, et les nouveaux utilisateurs avec un cache vide provoquent une explosion des requêtes
- Les outils GitOps (ArgoCD) rencontrent des problèmes de dépassement d’espace disque lors du clonage des dépôts
- Un seul commit invalide l’intégralité du cache, et les gros monorepos nécessitent un dimensionnement séparé
Pourquoi Git est structurellement mal adapté comme base de données
- Limites des répertoires : plus le nombre de fichiers augmente, plus cela ralentit
- CocoaPods devait gérer 16 000 répertoires, ce qui générait d’énormes objets d’arbre, problème résolu par un sharding fondé sur le hachage
- Problème de sensibilité à la casse : Git distingue les majuscules/minuscules, mais macOS et Windows non
- Azure DevOps a ajouté une fonction de blocage côté serveur pour éviter les conflits
- Limite de longueur des chemins : la limite de 260 caractères de Windows provoque des erreurs
git status - Absence de fonctions de base de données :
- Pas de contraintes CHECK/UNIQUE, pas de verrouillage, pas d’index, pas de migrations
- Chaque gestionnaire de paquets doit construire son propre système de validation et d’indexation
Conclusion
- Git est excellent pour la collaboration sur le code source, mais il est mal adapté aux requêtes sur les métadonnées de paquets et à la gestion de registres à grande échelle
- La plupart des gestionnaires de paquets finissent par migrer vers des index basés sur HTTP ou des bases de données
- Les avantages de Git (historique des versions, workflow de PR) sont attractifs, mais il échoue comme substitut à une base de données
- Lors de la conception d’un nouveau gestionnaire de paquets, même si un index Git paraît séduisant, on atteint les mêmes limites que dans les cas de Cargo, Homebrew, CocoaPods, vcpkg et Go
2 commentaires
Commentaires sur Hacker News
Cela ressemble à une forme de tragédie des biens communs. GitHub est gratuit et offre beaucoup d’excellentes fonctionnalités, donc tout le monde veut l’utiliser. Mais ce type de décision se produit toujours quand il existe des externalités.
L’externalité qui me paraît la plus importante, c’est le temps des utilisateurs. La plupart des entreprises de logiciels ne se préoccupent que du coût du temps d’ingénierie et ignorent le temps des utilisateurs. Elles se concentrent sur le développement de fonctionnalités, mais n’optimisent pas le temps d’interaction utilisateur. Par exemple, si je passe une heure à rendre une application plus rapide d’une seconde, un million d’utilisateurs économisent au total 277 heures par an. Mais comme le temps utilisateur est une externalité, ce genre d’optimisation est rarement fait
Au final, les utilisateurs téléchargent plus de données que nécessaire et attendent inutilement, tandis que les développeurs ne sont pas tenus responsables de ce gaspillage
Je travaille sur un Cargo/UV pour le C. C’est un excellent article, et je m’y reconnais beaucoup.
Quand on démarre, opérer un registre est vraiment difficile. Il ne faut pas seulement écrire du code, garantir la qualité de l’outil et faire grandir la communauté, mais aussi penser à une infrastructure capable d’absorber du trafic mondial. Dans ce contexte, une solution basée sur git est séduisante
Mais le vrai problème, c’est le sparse checkout. On veut versionner les manifestes de paquets avec git, mais il faut suivre des commits arbitraires, ce qui est inefficace. En pratique, cela impose de pousser deux commits, ce qui rend la chose irréaliste
À mon avis, l’approche de Conan est la plus pragmatique. Au lieu d’une reproductibilité parfaite, elle met de la logique conditionnelle dans le manifeste. Elle permet aussi d’associer des manifestes à des plages de versions. Ce n’est pas parfait, mais c’est un compromis pragmatique et utile.
Bien sûr, la vraie solution serait d’utiliser une base de données, mais comme personne ne va payer à votre place les serveurs et la maintenance, c’est difficile en pratique
Si le problème est l’argent et l’indépendance, une approche P2P est aussi possible. En revanche, sans cache CI, le trafic peut exploser
La structure de miroirs des distributions Linux comme Debian, Fedora ou openSUSE peut aussi servir d’inspiration
Cet article mélange deux problèmes. L’un est d’utiliser git comme base de données d’index de paquets, l’autre est de récupérer le code de chaque paquet via git. Ce sont deux sujets distincts.
On peut avoir l’index dans git et les paquets en zip/tar, ou l’inverse. Dans le cas de Go, il n’y a même pas d’index du tout
Les détails sur le backend de GitHub ou les 20 000 forks ne sont pas essentiels. On peut faire des consultations clé-valeur efficaces sans arbre de travail git.
L’idée que « réécrire l’historique git revient à faire une migration de base de données » est aussi étrange. Autant faire tourner un Postgres, non ?
L’approche « utilisons la solution la plus simple tant qu’elle fonctionne, et corrigeons plus tard si ça casse » est réaliste.
Julia fonctionne aussi de cette manière, et avec un volume de paquets d’environ un septième de celui de Rust, cela ne pose pas encore de problème.
On pourrait améliorer les choses en ne téléchargeant que le fichier racine Registry.toml, puis uniquement les paquets nécessaires. Ce n’est pas un gros problème
La culture du « Move fast and break things » est précisément ce qui nous a donné les logiciels lents et pleins de bugs d’aujourd’hui
Je suis d’accord avec la conclusion : « Git est une excellente base de données pour démarrer un gestionnaire de paquets »
Mon point de vue, c’est : « au final, ça a marché ». Pour l’exploitation au début, c’était largement suffisant, et les problèmes d’échelle ont pu être traités plus tard
Il y a ici un biais du survivant (survivorship bias). Si l’index git de Cargo a grossi au point de devenir un problème, c’est justement parce que Cargo a réussi.
La plupart des petits projets utilisent très bien git comme protocole de distribution de données.
Quand l’avenir en termes d’échelle est incertain au début, il est raisonnable d’utiliser git et GitHub pour se concentrer sur le problème essentiel
Chaque fois que je vois sur la page d’accueil de HN un article du type « ce que vous faites en ce moment est faux », ça me rend humble.
Ça m’est arrivé plusieurs fois aussi. Cette fois, c’était un article sur PG Notify.
Mais aujourd’hui, je développe seul, et je ne sais même pas si mon projet réussira, donc distribuer des plugins via git reste l’option la plus réaliste.
Cela dit, si un problème de montée en charge apparaît plus tard, je reviendrai à cet article
Personnellement, j’héberge mon code sur Forgejo. Il est protégé par mTLS sans exposition externe.
Mais les modules Go demandent un certificat, donc ils ne reconnaissent pas mon instance Forgejo.
Même avec SSH, il faut apparemment un accès HTTPS, donc j’ai fini par utiliser une copie locale via une directive
replace. C’est assez pénible.gità la fin du chemin du module et qu’on configure$GOPRIVATE, on peut utiliser l’authentification des commandes git sans requête HTTPS. Voir la documentation officielleBeaucoup de petits projets, pas seulement les gestionnaires de paquets, crowdsourcent leurs données dans des dépôts git.
La plupart restent à petite échelle et ne rencontrent donc pas les limites techniques.
En revanche, cette structure augmente la barrière à l’entrée pour les non-développeurs. Pour un gestionnaire de paquets, cela peut passer, mais pour des projets plus généralistes, c’est un vrai problème
Pour aider sur ce genre de sujet, j’ai créé une bibliothèque open source appelée Datatig.
Le support de présentation associé est disponible ici. À l’avenir, je compte m’appuyer sur cet article pour y ajouter aussi du contenu sur la montée en charge
On utilise git parce que c’est plus simple plutôt que de créer un système séparé pour recevoir les contributions des contributeurs. On parle de limites, mais ça ne me convainc pas vraiment, et je ne vois absolument aucune alternative aux problèmes concrets.