Caching Dependencies for Faster Builds
Speed up GitHub Actions workflows by caching npm, pip, Maven, or Gradle dependencies. Covers actions/cache, setup-action built-in caching, and cache key strategies.
Detailed Explanation
Dependency Caching in GitHub Actions
Caching dependencies between workflow runs can dramatically reduce build times — from minutes to seconds for dependency installation. GitHub Actions offers multiple caching approaches depending on your package manager.
Built-in Cache (Recommended)
Most setup actions include built-in caching:
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm' # or 'yarn' or 'pnpm'
Manual Cache with actions/cache
For more control, use actions/cache@v4 directly:
- name: Cache node_modules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
How Cache Keys Work
The cache system matches keys in order:
- Exact match:
runner.os-node-abc123— full cache hit, skip install entirely - Prefix match (restore-keys):
runner.os-node-— partial hit, restore closest match then install only changes - No match: Cold start, install everything from scratch
Framework-Specific Examples
Python with pip:
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
Gradle:
- uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
Cache Limits
- Maximum cache size per repository: 10 GB
- Caches not accessed in 7 days are automatically evicted
- When the limit is reached, the oldest caches are removed first
- Each cache entry can be up to 10 GB
Performance Impact
Typical time savings with caching:
- npm/yarn: 30-120 seconds saved per run
- pip: 15-60 seconds saved
- Gradle/Maven: 60-300 seconds saved
Use Case
Any CI workflow where dependency installation is a significant portion of the total run time. Most impactful for projects with large dependency trees (Node.js, Python, Java) or frequent workflow runs.