GitHub Actions Cache-Strategie: CI/CD-Pipeline 5× beschleunigen
npm install: 3 Minuten 15 Sekunden.
So lang war die CI-Build-Zeit eines Projekts, das ich letztes Jahr übernommen habe. Bei jedem Push starrte ich auf die GitHub Actions Logs und wartete auf den grünen Haken. Ehrlich gesagt wechselte ich oft zu anderen Tabs – Warten gehört dazu.
Mit Cache: derselbe Build in 40 Sekunden. Etwa fünfmal schneller.
Keine Magie – nur die richtige GitHub Actions Cache-Strategie. In diesem Artikel fasse ich Fallstricke, Messdaten und kopierfertige Konfigurationen zusammen. Wenn Sie auch auf CI warten, sparen Sie damit vermutlich viel Zeit.
1. Kernkonzepte des Cache-Mechanismus
Wer versteht, wie Cache arbeitet, konfiguriert ihn ohne böse Überraschungen.
GitHub Actions Cache folgt drei Schritten: Suchen → Wiederherstellen → Speichern. Sie definieren einen key; GitHub sucht einen passenden Cache. Gefunden wird ins Arbeitsverzeichnis restored; sonst wird nach dem Job ein neuer Cache gespeichert.
Wichtige Grenzen:
| Grenze | Wert |
|---|---|
| Cache-Obergrenze pro Repository | 10 GB |
| Maximale Größe einer Cache-Datei | 5 GB (über 1 GB wird es oft problematisch) |
| Aufbewahrung | 7 Tage ohne Zugriff → Löschung |
| Globale parallele Uploads | maximal 5 gleichzeitig |
Die 10-GB-Grenze kenne ich aus der Praxis: viele Abhängigkeiten, Cache wächst, neuer Cache passt nicht mehr, Altes wird entfernt – jeder Build startet „kalt“.
Cache und Artifact sind nicht dasselbe. Cache optimiert CI-Geschwindigkeit; Artifacts sind Build-Artefakte oder Reports für Menschen, oft länger haltbar. Cache: 10-GB-Limit; Artifacts: kein gleiches Limit, aber Repository-Speicher.
Docker Layer Cache ist ein eigener Mechanismus für Image-Builds – dazu später mehr.
2. Cache-Key-Design
Trefferquote hängt am key – das Herzstück der Strategie.
Was ist hashFiles()?
hashFiles() berechnet einen Hash – typisch für package-lock.json oder yarn.lock. Unveränderte Abhängigkeiten → gleicher Hash → Cache-Treffer.
key: npm-{{ runner.os }}-{{ hashFiles('**/package-lock.json') }}
Erzeugt z. B. npm-Linux-a1b2c3d4e5f6.... Ändert sich package-lock.json nicht, bleibt der key stabil.
restore-keys: Fallback
Bei Dependency-Updates helfen restore-keys als „abgestufte“ Suche:
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-{{ runner.os }}-{{ hashFiles('**/package-lock.json') }}
restore-keys: |
npm-{{ runner.os }}-
Zuerst exakter key; sonst der neueste Cache mit Präfix npm-Linux-. Nicht vollständiger Treffer, aber viele Pakete in node_modules sind schon da – nur Delta-Installation nötig.
Drei Key-Muster im Vergleich
Aus Tests empfehle ich:
Einfach (kleine Projekte):
key: {{ runner.os }}-node-{{ hashFiles('**/package-lock.json') }}
Mit Version (mehrere Node-Versionen):
key: {{ runner.os }}-node{{ matrix.node-version }}-{{ hashFiles('**/package-lock.json') }}
Mehrere Pfade (Monorepo):
key: {{ runner.os }}-{{ hashFiles('**/package-lock.json', '**/yarn.lock') }}
Treffer erkennen
actions/cache liefert cache-hit:
- uses: actions/cache@v4
id: cache-npm
with:
path: ~/.npm
key: {{ runner.os }}-node-{{ hashFiles('**/package-lock.json') }}
- name: Check cache hit
run: echo "Cache hit - {{ steps.cache-npm.outputs.cache-hit }}"
true = exakter Treffer; false = Teil-Treffer oder Miss. Damit können Sie npm ci bedingt ausführen:
- name: Install dependencies
if: steps.cache-npm.outputs.cache-hit != 'true'
run: npm ci
3. Praxis-Konfigurationen
Theorie reicht – hier getestete Snippets zum Kopieren.
npm (setup-node empfohlen)
setup-node hat eingebautes Caching – oft schlanker als manuelles actions/cache:
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # oder 'yarn', 'pnpm'
Eine Zeile. Für andere Verzeichnisse (z. B. node_modules) weiterhin actions/cache:
- uses: actions/cache@v4
with:
path: node_modules
key: {{ runner.os }}-nm-{{ hashFiles('**/package-lock.json') }}
restore-keys: {{ runner.os }}-nm-
Empfehlung: Zuerst eingebautes Cache von setup-node, außer bei Sonderfällen.
yarn und pnpm
yarn nutzt andere Pfade:
- uses: actions/cache@v4
with:
path: |
~/.yarn/cache
~/.yarn/install-state.gz
key: yarn-{{ runner.os }}-{{ hashFiles('**/yarn.lock') }}
pnpm mit globalem Store:
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: pnpm-{{ runner.os }}-{{ hashFiles('**/pnpm-lock.yaml') }}
Python/pip
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-{{ runner.os }}-{{ hashFiles('**/requirements.txt') }}
restore-keys: pip-{{ runner.os }}-
Docker Layer Cache
Image-Builds sind teuer; BuildKit unterstützt den GitHub Actions Cache-Backend:
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
context: .
push: false
cache-from: type=gha
cache-to: type=gha,mode=max
type=gha speichert Layer im Actions-Cache. In Tests: 5-Minuten-Build oft unter 1 Minute.
Go-Module
- uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: go-{{ runner.os }}-{{ hashFiles('**/go.sum') }}
Rust Cargo
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: cargo-{{ runner.os }}-{{ hashFiles('**/Cargo.lock') }}
Rust-Compile profitiert stark; target wächst jedoch – gelegentlich aufräumen.
4. Performance und Best Practices
Messdaten und typische Fehler aus der Praxis.
Benchmarks
Laut RunsOn-Report (Stand Januar 2026) mit sinnvollem Cache:
| Vorgang | Ohne Cache | Mit Cache | Faktor |
|---|---|---|---|
| npm install | 3 Min. | 40 Sek. | ~5× |
| yarn install | 2 Min. 30 Sek. | 35 Sek. | ~4× |
| Docker build | 5 Min. | 1 Min. | ~5× |
| pip install | 45 Sek. | 8 Sek. | ~5× |
Trefferquote typisch 70–90 % – abhängig vom Key-Design.
Häufige Fallen
Nicht direkt node_modules cachen
# So nicht
path: node_modules
node_modules ist plattformabhängig – Linux-Pakete können auf Windows scheitern. Besser globalen Cache (~/.npm) und npm ci lokal zusammensetzen.
Cross-OS: GNU tar + zstd
Standard-tar unterscheidet sich auf macOS/Windows – Restore kann scheitern:
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-{{ runner.os }}-{{ hashFiles('**/package-lock.json') }}
enableCrossOsArchive: true
Cache-Verunreinigung
Defekte Abhängigkeiten im Cache → wiederholte Build-Fehler:
- Manuell löschen: Repository → Actions → Caches
- Key erzwingen: Präfix oder Version im key
key: npm-v2-{{ runner.os }}-{{ hashFiles('**/package-lock.json') }}
Checkliste
Vor dem Rollout prüfen:
- Eingebautes Cache in offiziellen Actions (setup-node, setup-python)
- hashFiles im key, damit Dependency-Updates den Cache invalidieren
- restore-keys für Teil-Treffer
- Kein
node_modules-Cache, globale Verzeichnisse nutzen - Alte Caches löschen, unter 10 GB bleiben
5. Häufige Fragen
F1: Niedrige Trefferquote?
Oft wechselt der key zu oft – Zeitstempel oder Branch im key. Lösung: nur runner.os und hashFiles.
Oder hashFiles trifft zu viele Dateien, z. B. hashFiles('**/*.json') – jede Config-Änderung invalidiert. Nur package-lock.json / yarn.lock matchen.
F2: Cache-Speicher voll?
10 GB reichen nicht für große Monorepos oder Docker-Layer. Lösungen:
- Actions → Caches manuell aufräumen
- Getrennte keys pro Abhängigkeitstyp
- self-hosted runners ohne 10-GB-Limit
F3: self-hosted runners?
Gleiche Konfiguration. Vorteil: lokaler Cache, kein Netzwerk-Restore. Nachteil: keine Auto-Bereinigung – eigene Wartung.
F4: Cache erzwingen aktualisieren?
Key-Version erhöhen:
key: npm-v3-{{ runner.os }}-{{ hashFiles('**/package-lock.json') }}
Oder alten Cache in der UI löschen.
Zusammenfassung
Kurz gesagt: gut konfigurierter Cache macht CI etwa fünfmal schneller.
Rechnen wir: 2 Minuten pro Build gespart, 10 Läufe täglich → 600 Minuten im Monat, rund 10 Stunden – Zeit für mehrere Artikel.
Einsteiger: mit setup-node und cache: 'npm' starten. Bei Engpässen Key-Strategie und Docker Layer Cache vertiefen.
Dies ist Teil 3 der Serie „GitHub Actions Praxis“. Zuvor: Pipeline-Aufbau und Deployment – in älteren Beiträgen nachlesen.
Beim nächsten Push die Build-Zeit prüfen: von 3 Minuten auf 40 Sekunden – ausprobieren lohnt sich.
GitHub Actions Cache für schnelleres CI/CD einrichten
Mit GitHub Actions Cache die npm-install-Zeit von 3 Minuten auf 40 Sekunden reduzieren
⏱️ Estimated time: 10 min
- 1
Step 1: Cache-Strategie wählen
Je nach Paketmanager:
• npm: setup-node mit eingebautem Cache
• yarn/pnpm: Cache-Pfade konfigurieren
• Docker: BuildKit-Backend gha nutzen - 2
Step 2: Cache-Key entwerfen
hashFiles() auf Basis der Lock-Datei:
• Basis: {{ runner.os }}-node-{{ hashFiles('**/package-lock.json') }}
• restore-keys als Fallback
• Keine Zeitstempel oder Branch-Namen im key - 3
Step 3: Cache-Konfiguration ergänzen
Im Workflow:
• npm: actions/setup-node@v4, cache: 'npm'
• Eigene Pfade: actions/cache@v4
• Docker: cache-from und cache-to setzen - 4
Step 4: Cache-Wirkung prüfen
Treffer prüfen:
• Ausgabe cache-hit (true = exakter Treffer)
• Build-Zeit vergleichen (4–5× schneller)
• Actions → Caches: Eintrag vorhanden - 5
Step 5: Cache regelmäßig pflegen
Probleme vermeiden:
• Speicher beobachten (Limit 10 GB)
• Alte Caches löschen
• Bei Verunreinigung Key-Präfix ändern
FAQ
Warum liegt die Cache-Trefferquote nur bei 30 %?
Was passiert bei mehr als 10 GB Cache?
• Abhängigkeitstypen getrennt cachen (npm, Docker, pip mit eigenem key)
• Unter Actions → Caches manuell aufräumen
• Monorepos: Repositorys trennen oder self-hosted runners
Können Branches Cache teilen?
Was ist bei self-hosted runners anders?
Bricht ein fehlgeschlagenes Cache-Restore den Build ab?
Wann muss der Cache aktualisiert werden?
• Abhängigkeitsversionen: hashFiles automatisch
• Cache-Verunreinigung: Build bricht plötzlich ab – alten Cache löschen
• Konfigurationsänderung: z. B. Node-Version – Versionsnummer im key
Bei korrekter Konfiguration meist kein manuelles Management nötig.
5 Min. Lesezeit · Veröffentlicht am: 7. Apr. 2026 · Aktualisiert am: 9. Juli 2026
GitHub Actions Komplettleitfaden
Wenn du über die Suche hier gelandet bist, kommst du am schnellsten weiter, indem du zum vorherigen oder nächsten Beitrag dieser Serie springst.
Vorheriger
GitHub Actions CI-Pipeline in der Praxis: Build und Test automatisieren
GitHub Actions CI-Pipeline Schritt für Schritt: Workflow-Konfiguration, Matrix-Tests über mehrere Versionen, Cache-Optimierung und Praxis-Tipps für automatisierten Build und Test.
Teil 2 von 10
Nächster
GitHub Actions Matrix-Build: Parallele Multi-Version-Tests in der Praxis
Praxisleitfaden zu GitHub Actions Matrix: Basis-Syntax, exclude/include-Filter, fail-fast-Optimierung und max-parallel-Ressourcensteuerung – mit vollständiger Vorlage für parallele Multi-Version-Tests.
Teil 4 von 10
Ähnliche Beiträge
GitHub Actions Einstieg: YAML-Workflow-Grundlagen und Trigger-Konfiguration

GitHub Actions Einstieg: YAML-Workflow-Grundlagen und Trigger-Konfiguration
GitHub Actions Matrix-Build: Parallele Tests auf mehreren Plattformen und Versionen


Kommentare
Melde dich mit GitHub an, um einen Kommentar zu hinterlassen