- Mehrere Paketmanager nutzten Git wie eine Datenbank, weil Versionsverwaltung und Zusammenarbeit bequem sind, stießen mit wachsender Größe jedoch auf Performance- und Wartungsprobleme
- Cargo, Homebrew und CocoaPods wechselten schließlich wegen der wachsenden Größe ihrer Git-Indizes, langsamer Updates und Ineffizienz in CI-Umgebungen zu HTTP-basierten Indizes oder CDNs
- vcpkg arbeitet weiterhin auf Basis von Git-Tree-Hashes; in Umgebungen mit flachen Klonen (shallow clone) kommt es zu Build-Fehlschlägen und komplizierten Workarounds
- Das Go-Modulsystem führte GOPROXY und eine Prüfsummendatenbank (sumdb) ein, entfernte damit die Git-Abhängigkeit und verbesserte Sicherheit und Geschwindigkeit
- Git ist für die Zusammenarbeit an Code hervorragend geeignet, erweist sich jedoch immer wieder als ungeeignet für Paket-Metadatenabfragen oder die Verwaltung großer Register
Das wiederholte Scheitern von Versuchen, Git als Datenbank zu verwenden
- Git ist wegen Vorteilen wie Versionshistorie, verteilter Struktur und kostenlosem Hosting attraktiv, stößt als Datenbank aber an Skalierungsgrenzen
- Mehrere Paketmanager übernahmen Git als Index, doch mit der Zeit nahmen Leistungseinbußen und Infrastrukturbelastung zu
Cargo
- Der crates.io-Index begann als Git-Repository, und alle Clients führten eine vollständige Replikation (clone) durch
- Als das Repository wuchs, entstand in der Delta-Resolution-Phase ein Performance-Flaschenhals in libgit2
- In CI-Umgebungen wurde bei jedem Build der komplette Index heruntergeladen, was zu erheblicher Verschwendung führte
- Mit RFC 2789 wurde das sparse-HTTP-Protokoll eingeführt, sodass nur die benötigten Metadaten per HTTPS abgerufen werden
- Stand April 2025 nutzen 99 % der Anfragen den sparse-Modus
- Der Git-Index existiert weiterhin, wird von den meisten Nutzern aber nicht mehr verwendet
Homebrew
- GitHub bat Homebrew darum, keine flachen Klone mehr zu verwenden; Updates wurden als „sehr teure Operation“ bezeichnet
- Der
.git-Ordner von homebrew-core nähert sich 1 GB, und bei Updates kommt es durch Delta Resolution zu Verzögerungen
- Der
- Im Februar 2023 stellte Homebrew 4.0.0 Tap-Updates auf einen JSON-Download-Mechanismus um
- Durch den Wegfall von Git fetch wurden Updates schneller, und der automatische Update-Zyklus änderte sich von 5 Minuten auf 24 Stunden
CocoaPods
- Beim Paketmanager CocoaPods für iOS/macOS wurde das aus Hunderttausenden podspecs bestehende Specs-Repository übermäßig groß
- Klonen und Aktualisieren dauerten mehrere Minuten, und der Großteil der CI-Zeit ging für Git-Operationen drauf
- GitHub führte ein CPU-Rate-Limit ein; flache Klone wurden als Ursache der Serverlast benannt
- Das Team setzte Übergangsmaßnahmen wie das Abschalten automatischer Fetches, den Wechsel zu vollständigen Klonen und das Sharding des Repositorys um
- Ab Version 1.8 erfolgte der Wechsel zu CDN-basierter HTTP-Auslieferung, wodurch bei Nutzern etwa 1 GB Speicherplatz eingespart und die Installationsgeschwindigkeit deutlich verbessert wurde
Nixpkgs
- Nix vermeidet auf Client-Seite bereits Git-Klone durch tarball-basierte Channels
- Paketausdrücke werden per HTTP über S3 und CDN bereitgestellt
- Die Infrastruktur von GitHub wird jedoch durch ein 83-GB-Repository und 20.000 Forks belastet
- Im November 2025 meldete GitHub fehlgeschlagene Einigungen zwischen Replikaten und Fehler bei Wartungsarbeiten
- Lokale Klone sind zwar 2,5 GB groß, aber das gesamte Fork-Netzwerk belastet den GitHub-Speicher stark
vcpkg
- vcpkg, der C++-Paketmanager von Microsoft, versioniert mit Git-Tree-Hashes
- Um über
builtin-baselinedie Ports eines bestimmten Commit-Zeitpunkts reproduzieren zu können, wird die vollständige Historie benötigt
- Um über
- In Umgebungen mit flachen Klonen (GitHub Actions, DevContainers) schlagen Builds fehl
- Als Lösung ist die Einstellung
fetch-depth: 0nötig, was den Download der gesamten Historie erfordert
- Als Lösung ist die Einstellung
- Aufgrund der Struktur von Git-Tree-Hashes ist kein Commit-Tracking möglich; das Problem ist wegen struktureller Grenzen nicht behebbar
- Unterstützt werden weiterhin nur registerbasierte Git-Repositories, HTTP- oder CDN-Alternativen gibt es nicht
Go-Modulsystem
- Das Engineering-Team von Grab verkürzte nach Einführung eines Modul-Proxys die Zeit für
go getvon 18 Minuten auf 12 Sekunden - Im bisherigen Verfahren musste das gesamte Repository jeder Abhängigkeit geklont werden, um
go.modlesen zu können - Das Go-Team hatte Bedenken wegen der Abhängigkeit von VCS-Werkzeugen und Sicherheitslücken
- Seit Go 1.13 ist GOPROXY der Standard; Modulquellen und
go.modwerden per HTTP bereitgestellt- sumdb (Prüfsummendatenbank) gewährleistet Integrität und Dauerhaftigkeit der Module
Allgemeine Probleme beim Einsatz von Git als Datenbank
- Git-basiertes Wiki (Gollum) wird bei großen Repositories bei der Verzeichnisnavigation und beim Laden von Seiten langsam
- GitLab plant, die Nutzung von Gollum einzustellen
- Git-basiertes CMS (Decap) stößt an das GitHub-API-Limit von 5.000 Anfragen
- Ab etwa 10.000 Einträgen sinkt die Leistung, und neue Nutzer mit leerem Cache verursachen eine Anfragenflut
- GitOps-Tool (ArgoCD) hat beim Klonen von Repositories Probleme mit überschrittenem Speicherplatz
- Ein einzelner Commit invalidiert den gesamten Cache, und große Monorepos benötigen gesonderte Skalierung
Strukturelle Gründe, warum Git als Datenbank ungeeignet ist
- Verzeichnisgrenzen: Mit steigender Dateizahl wird Git langsamer
- CocoaPods erzeugte wegen 16.000 Verzeichnissen riesige Tree-Objekte und löste das Problem durch hashbasiertes Sharding
- Groß-/Kleinschreibung: Git unterscheidet sie, macOS und Windows jedoch nicht
- Azure DevOps ergänzte serverseitige Sperren, um Konflikte zu verhindern
- Beschränkung der Pfadlänge: Das Windows-Limit von 260 Zeichen verursacht Fehler bei
git status - Fehlende Datenbankfunktionen:
- Es gibt keine CHECK-/UNIQUE-Constraints, keine Sperren, keine Indizes und keine Migrationsfunktionen
- Jeder Paketmanager muss eigene Systeme für Validierung und Indizierung aufbauen
Fazit
- Git ist für die Zusammenarbeit an Quellcode hervorragend geeignet, jedoch ungeeignet für Paket-Metadatenabfragen oder die Verwaltung großer Register
- Die meisten Paketmanager wechseln am Ende zu HTTP-basierten Indizes oder Datenbanken
- Die Vorteile von Git (Versionshistorie, PR-Workflow) sind attraktiv, doch als Datenbankersatz scheitert es
- Auch wenn ein Git-Index beim Entwurf eines neuen Paketmanagers attraktiv wirkt, stößt man wie bei Cargo, Homebrew, CocoaPods, vcpkg und Go auf dieselben Grenzen
2 Kommentare
Hacker-News-Kommentare
Das wirkt wie eine Art Tragödie der Allmende. GitHub ist kostenlos und bietet viele großartige Funktionen, also wollen es alle nutzen. Aber solche Entscheidungen treten immer dann auf, wenn es Externalitäten gibt.
Die für mich wichtigste Externalität ist die Zeit der Nutzer. Die meisten Softwareunternehmen achten nur auf die Kosten der Engineering-Zeit und ignorieren die Zeit der Nutzer. Sie konzentrieren sich auf die Entwicklung von Features, optimieren aber nicht die Zeit, die für die Interaktion der Nutzer benötigt wird. Wenn ich zum Beispiel 1 Stunde darauf verwende, eine App 1 Sekunde schneller zu machen, sparen eine Million Nutzer pro Jahr 277 Stunden. Aber weil Nutzerzeit eine Externalität ist, findet diese Art von Optimierung fast nie statt
Am Ende laden Nutzer unnötig mehr Daten herunter und warten länger, und die Entwickler tragen für diese Verschwendung keine Verantwortung
Ich baue Cargo/UV für C. Toller Artikel, ich kann dem sehr gut nachfühlen.
Gerade am Anfang ist der Betrieb einer Registry wirklich schwierig. Man muss sich nicht nur um das Schreiben von Code, die Qualität der Tools und den Community-Aufbau kümmern, sondern auch um Infrastruktur, die weltweiten Traffic verkraftet. In so einer Situation ist eine Git-basierte Lösung attraktiv
Das Problem ist aber sparse checkout. Ich möchte Paketmanifeste per git versionieren, aber weil beliebige Commits nachverfolgt werden müssen, ist das ineffizient. Am Ende entsteht eine Struktur, in der man zwei Commits pushen muss, was in der Praxis kaum machbar ist
Ich halte den Ansatz von Conan für am praktikabelsten. Statt perfekter Reproduzierbarkeit packt man bedingte Logik in das Manifest. Auch ein Mapping von Manifesten nach Versionsbereichen ist möglich. Nicht perfekt, aber ein praktischer und nützlicher Kompromiss.
Natürlich wäre die echte Lösung eine Datenbank, aber da einem niemand die Server- und Betriebskosten abnimmt, ist das realistisch schwer umzusetzen
Wenn Geld und Unabhängigkeit das Problem sind, wäre auch ein P2P-Ansatz möglich. Wenn allerdings CI-Caching nicht funktioniert, kann der Traffic explodieren
Als Referenz taugt auch die Mirror-Struktur von Linux-Distributionen wie Debian, Fedora oder openSUSE
Dieser Artikel vermischt zwei Probleme. Das eine ist, git als Datenbank für einen Paketindex zu verwenden, das andere, den Code jedes Pakets per git zu holen. Das sind getrennte Dinge.
Den Index kann man in git haben und die Pakete als zip/tar ausliefern, oder umgekehrt. Bei Go gibt es sogar gar keinen Index
Dinge wie GitHubs Backend-Implementierung oder 20.000 Forks sind für den Kern des Problems irrelevant. Auch ohne Git-Working-Tree sind effiziente Key-Value-Lookups möglich.
Die Behauptung, „Git-History-Rewrites entsprächen DB-Migrationen“, ist ebenfalls seltsam. Wäre es dann nicht besser, einfach eine Postgres-Instanz zu betreiben?
Der Ansatz „Nimm die einfache Lösung, solange sie funktioniert, und repariere es, wenn sie nicht mehr funktioniert“ ist realistisch.
Julia macht es genauso, und weil es im Vergleich zu Rust nur etwa ein Siebtel so viele Pakete gibt, ist es bisher kein Problem.
Man könnte das verbessern, indem man nur die oberste Registry.toml-Datei abruft und dann nur die benötigten Pakete herunterlädt. Kein großes Problem
Die Kultur von „Move fast and break things“ hat die langsame und fehleranfällige Software hervorgebracht, die wir heute sehen
Ich stimme der Schlussfolgerung zu: „Git ist als Datenbank für den Start eines Paketmanagers hervorragend geeignet“
Ich vertrete eher die Position „Am Ende hat es doch funktioniert“. Für den frühen Betrieb war es völlig ausreichend hilfreich, und Skalierungsprobleme ließen sich später lösen
Hier steckt Survivorship Bias drin. Dass der Git-Index von Cargo groß wurde und Probleme verursachte, liegt daran, dass Cargo erfolgreich war.
Die meisten kleinen Projekte nutzen git als Datenverteilungsprotokoll ganz problemlos.
In einer frühen Phase, in der unklar ist, ob man überhaupt skaliert, ist es vernünftig, git und GitHub zu nutzen, um sich auf das Kernproblem zu konzentrieren
Wenn ich auf der HN-Startseite einen Artikel mit dem Tenor „Was du gerade machst, ist falsch“ sehe, macht mich das immer demütig.
So etwas ist mir auch schon ein paar Mal passiert. Diesmal war es ein Artikel über PG Notify.
Aber im Moment entwickle ich allein, und ich weiß nicht einmal, ob das Projekt überhaupt erfolgreich sein wird, also ist git für die Plugin-Verteilung am realistischsten.
Wenn später Skalierungsprobleme auftauchen, werde ich diesen Artikel trotzdem als Referenz heranziehen
Ich hoste meinen Code persönlich mit Forgejo. Nach außen ist er nicht exponiert und mit mTLS geschützt.
Aber Go-Module verlangen ein Zertifikat und erkennen meine Forgejo-Instanz deshalb nicht.
Selbst mit SSH hieß es, HTTPS-Zugriff sei nötig, daher verwende ich am Ende mit einer replace directive eine lokale Kopie. Ziemlich umständlich
.gitan das Ende des Modulpfads hängt und$GOPRIVATEsetzt, kann man Git-Befehlsauthentifizierung ohne HTTPS-Anfragen nutzen. Siehe offizielle DokumentationNicht nur Paketmanager, sondern auch viele kleine Projekte crowdsourcen Daten in Git-Repositories.
Die meisten sind so klein, dass sie nie an technische Grenzen stoßen.
Allerdings erhöht diese Struktur die Hürde für Nicht-Entwickler, sich zu beteiligen. Bei Paketmanagern ist das eine Ausnahme, bei allgemeinen Projekten ist es ein Problem
Um bei solchen Problemen zu helfen, habe ich eine Open-Source-Bibliothek namens Datatig erstellt.
Das zugehörige Vortragsmaterial ist hier zu finden. Ich werde mich künftig auf diesen Artikel beziehen und auch Inhalte zum Thema Skalierung ergänzen
Man nutzt eben Git, weil es unkompliziert ist, statt eigens ein separates System aufzubauen, um Beiträge von Mitwirkenden anzunehmen. Dass das eine Grenze sein soll, überzeugt mich nicht besonders, und eine Alternative für die realen Probleme ist überhaupt nicht zu sehen.